2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
143 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
144 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
150 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
151 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
155 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
156 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
159 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
164 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
167 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
172 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
173 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
174 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
175 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
176 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
178 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
186 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
187 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
188 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
189 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
191 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
192 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
193 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
194 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
195 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
196 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
197 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
199 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
200 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
213 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
215 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
217 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
222 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
224 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
226 extern cvar_t v_glslgamma;
227 extern cvar_t v_glslgamma_2d;
229 extern qboolean v_flipped_state;
231 static struct r_bloomstate_s
236 int bloomwidth, bloomheight;
238 textype_t texturetype;
239 int viewfbo; // used to check if r_viewfbo cvar has changed
241 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
245 int screentexturewidth, screentextureheight;
246 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
248 int bloomtexturewidth, bloomtextureheight;
249 rtexture_t *texture_bloom;
251 // arrays for rendering the screen passes
252 float screentexcoord2f[8];
253 float bloomtexcoord2f[8];
254 float offsettexcoord2f[8];
256 r_viewport_t viewport;
260 r_waterstate_t r_waterstate;
262 /// shadow volume bsp struct with automatically growing nodes buffer
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
287 int r_texture_numcubemaps;
288 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
294 typedef struct r_qwskincache_s
296 char name[MAX_QPATH];
297 skinframe_t *skinframe;
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
314 const float r_d3dscreenvertex3f[12] =
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
325 for (i = 0;i < verts;i++)
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
339 for (i = 0;i < verts;i++)
349 // FIXME: move this to client?
352 if (gamemode == GAME_NEHAHRA)
354 Cvar_Set("gl_fogenable", "0");
355 Cvar_Set("gl_fogdensity", "0.2");
356 Cvar_Set("gl_fogred", "0.3");
357 Cvar_Set("gl_foggreen", "0.3");
358 Cvar_Set("gl_fogblue", "0.3");
360 r_refdef.fog_density = 0;
361 r_refdef.fog_red = 0;
362 r_refdef.fog_green = 0;
363 r_refdef.fog_blue = 0;
364 r_refdef.fog_alpha = 1;
365 r_refdef.fog_start = 0;
366 r_refdef.fog_end = 16384;
367 r_refdef.fog_height = 1<<30;
368 r_refdef.fog_fadedepth = 128;
369 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
372 static void R_BuildBlankTextures(void)
374 unsigned char data[4];
375 data[2] = 128; // normal X
376 data[1] = 128; // normal Y
377 data[0] = 255; // normal Z
378 data[3] = 128; // height
379 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 static void R_BuildNoTexture(void)
400 unsigned char pix[16][16][4];
401 // this makes a light grey/dark grey checkerboard texture
402 for (y = 0;y < 16;y++)
404 for (x = 0;x < 16;x++)
406 if ((y < 8) ^ (x < 8))
422 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
425 static void R_BuildWhiteCube(void)
427 unsigned char data[6*1*1*4];
428 memset(data, 255, sizeof(data));
429 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
432 static void R_BuildNormalizationCube(void)
436 vec_t s, t, intensity;
439 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440 for (side = 0;side < 6;side++)
442 for (y = 0;y < NORMSIZE;y++)
444 for (x = 0;x < NORMSIZE;x++)
446 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
482 intensity = 127.0f / sqrt(DotProduct(v, v));
483 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486 data[((side*64+y)*64+x)*4+3] = 255;
490 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
494 static void R_BuildFogTexture(void)
498 unsigned char data1[FOGWIDTH][4];
499 //unsigned char data2[FOGWIDTH][4];
502 r_refdef.fogmasktable_start = r_refdef.fog_start;
503 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504 r_refdef.fogmasktable_range = r_refdef.fogrange;
505 r_refdef.fogmasktable_density = r_refdef.fog_density;
507 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
510 d = (x * r - r_refdef.fogmasktable_start);
511 if(developer_extra.integer)
512 Con_DPrintf("%f ", d);
514 if (r_fog_exp2.integer)
515 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
517 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518 if(developer_extra.integer)
519 Con_DPrintf(" : %f ", alpha);
520 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521 if(developer_extra.integer)
522 Con_DPrintf(" = %f\n", alpha);
523 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
526 for (x = 0;x < FOGWIDTH;x++)
528 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
533 //data2[x][0] = 255 - b;
534 //data2[x][1] = 255 - b;
535 //data2[x][2] = 255 - b;
538 if (r_texture_fogattenuation)
540 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
550 static void R_BuildFogHeightTexture(void)
552 unsigned char *inpixels;
560 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561 if (r_refdef.fogheighttexturename[0])
562 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
565 r_refdef.fog_height_tablesize = 0;
566 if (r_texture_fogheighttexture)
567 R_FreeTexture(r_texture_fogheighttexture);
568 r_texture_fogheighttexture = NULL;
569 if (r_refdef.fog_height_table2d)
570 Mem_Free(r_refdef.fog_height_table2d);
571 r_refdef.fog_height_table2d = NULL;
572 if (r_refdef.fog_height_table1d)
573 Mem_Free(r_refdef.fog_height_table1d);
574 r_refdef.fog_height_table1d = NULL;
578 r_refdef.fog_height_tablesize = size;
579 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
583 // LordHavoc: now the magic - what is that table2d for? it is a cooked
584 // average fog color table accounting for every fog layer between a point
585 // and the camera. (Note: attenuation is handled separately!)
586 for (y = 0;y < size;y++)
588 for (x = 0;x < size;x++)
594 for (j = x;j <= y;j++)
596 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602 for (j = x;j >= y;j--)
604 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
615 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
618 //=======================================================================================================================================================
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *vertexfilename;
643 const char *geometryfilename;
644 const char *fragmentfilename;
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
653 {"#define USEDIFFUSE\n", " diffuse"},
654 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655 {"#define USEVIEWTINT\n", " viewtint"},
656 {"#define USECOLORMAPPING\n", " colormapping"},
657 {"#define USESATURATION\n", " saturation"},
658 {"#define USEFOGINSIDE\n", " foginside"},
659 {"#define USEFOGOUTSIDE\n", " fogoutside"},
660 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662 {"#define USEGAMMARAMPS\n", " gammaramps"},
663 {"#define USECUBEFILTER\n", " cubefilter"},
664 {"#define USEGLOW\n", " glow"},
665 {"#define USEBLOOM\n", " bloom"},
666 {"#define USESPECULAR\n", " specular"},
667 {"#define USEPOSTPROCESSING\n", " postprocessing"},
668 {"#define USEREFLECTION\n", " reflection"},
669 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678 {"#define USEALPHAKILL\n", " alphakill"},
679 {"#define USEREFLECTCUBE\n", " reflectcube"},
680 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681 {"#define USEBOUNCEGRID\n", " bouncegrid"},
682 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683 {"#define USETRIPPY\n", " trippy"},
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
709 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
727 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731 struct r_glsl_permutation_s;
732 typedef struct r_glsl_permutation_s
735 struct r_glsl_permutation_s *hashnext;
737 unsigned int permutation;
739 /// indicates if we have tried compiling this permutation already
741 /// 0 if compilation failed
743 // texture units assigned to each detected uniform
744 int tex_Texture_First;
745 int tex_Texture_Second;
746 int tex_Texture_GammaRamps;
747 int tex_Texture_Normal;
748 int tex_Texture_Color;
749 int tex_Texture_Gloss;
750 int tex_Texture_Glow;
751 int tex_Texture_SecondaryNormal;
752 int tex_Texture_SecondaryColor;
753 int tex_Texture_SecondaryGloss;
754 int tex_Texture_SecondaryGlow;
755 int tex_Texture_Pants;
756 int tex_Texture_Shirt;
757 int tex_Texture_FogHeightTexture;
758 int tex_Texture_FogMask;
759 int tex_Texture_Lightmap;
760 int tex_Texture_Deluxemap;
761 int tex_Texture_Attenuation;
762 int tex_Texture_Cube;
763 int tex_Texture_Refraction;
764 int tex_Texture_Reflection;
765 int tex_Texture_ShadowMap2D;
766 int tex_Texture_CubeProjection;
767 int tex_Texture_ScreenDepth;
768 int tex_Texture_ScreenNormalMap;
769 int tex_Texture_ScreenDiffuse;
770 int tex_Texture_ScreenSpecular;
771 int tex_Texture_ReflectMask;
772 int tex_Texture_ReflectCube;
773 int tex_Texture_BounceGrid;
774 /// locations of detected uniforms in program object, or -1 if not found
775 int loc_Texture_First;
776 int loc_Texture_Second;
777 int loc_Texture_GammaRamps;
778 int loc_Texture_Normal;
779 int loc_Texture_Color;
780 int loc_Texture_Gloss;
781 int loc_Texture_Glow;
782 int loc_Texture_SecondaryNormal;
783 int loc_Texture_SecondaryColor;
784 int loc_Texture_SecondaryGloss;
785 int loc_Texture_SecondaryGlow;
786 int loc_Texture_Pants;
787 int loc_Texture_Shirt;
788 int loc_Texture_FogHeightTexture;
789 int loc_Texture_FogMask;
790 int loc_Texture_Lightmap;
791 int loc_Texture_Deluxemap;
792 int loc_Texture_Attenuation;
793 int loc_Texture_Cube;
794 int loc_Texture_Refraction;
795 int loc_Texture_Reflection;
796 int loc_Texture_ShadowMap2D;
797 int loc_Texture_CubeProjection;
798 int loc_Texture_ScreenDepth;
799 int loc_Texture_ScreenNormalMap;
800 int loc_Texture_ScreenDiffuse;
801 int loc_Texture_ScreenSpecular;
802 int loc_Texture_ReflectMask;
803 int loc_Texture_ReflectCube;
804 int loc_Texture_BounceGrid;
806 int loc_BloomBlur_Parameters;
808 int loc_Color_Ambient;
809 int loc_Color_Diffuse;
810 int loc_Color_Specular;
814 int loc_DeferredColor_Ambient;
815 int loc_DeferredColor_Diffuse;
816 int loc_DeferredColor_Specular;
817 int loc_DeferredMod_Diffuse;
818 int loc_DeferredMod_Specular;
819 int loc_DistortScaleRefractReflect;
822 int loc_FogHeightFade;
824 int loc_FogPlaneViewDist;
825 int loc_FogRangeRecip;
828 int loc_LightPosition;
829 int loc_OffsetMapping_ScaleSteps;
830 int loc_OffsetMapping_LodDistance;
832 int loc_ReflectColor;
833 int loc_ReflectFactor;
834 int loc_ReflectOffset;
835 int loc_RefractColor;
837 int loc_ScreenCenterRefractReflect;
838 int loc_ScreenScaleRefractReflect;
839 int loc_ScreenToDepth;
840 int loc_ShadowMap_Parameters;
841 int loc_ShadowMap_TextureScale;
842 int loc_SpecularPower;
847 int loc_ViewTintColor;
849 int loc_ModelToLight;
851 int loc_BackgroundTexMatrix;
852 int loc_ModelViewProjectionMatrix;
853 int loc_ModelViewMatrix;
854 int loc_PixelToScreenTexCoord;
855 int loc_ModelToReflectCube;
856 int loc_ShadowMapMatrix;
857 int loc_BloomColorSubtract;
858 int loc_NormalmapScrollBlend;
859 int loc_BounceGridMatrix;
860 int loc_BounceGridIntensity;
862 r_glsl_permutation_t;
864 #define SHADERPERMUTATION_HASHSIZE 256
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
871 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
877 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
880 #define SHADERSTATICPARMS_COUNT 8
882 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
883 static int shaderstaticparms_count = 0;
885 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
886 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
887 qboolean R_CompileShader_CheckStaticParms(void)
889 static int r_compileshader_staticparms_save[1];
890 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
891 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
894 if (r_glsl_saturation_redcompensate.integer)
895 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
896 if (r_glsl_vertextextureblend_usebothalphas.integer)
897 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
898 if (r_shadow_glossexact.integer)
899 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
900 if (r_glsl_postprocess.integer)
902 if (r_glsl_postprocess_uservec1_enable.integer)
903 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
904 if (r_glsl_postprocess_uservec2_enable.integer)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
906 if (r_glsl_postprocess_uservec3_enable.integer)
907 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
908 if (r_glsl_postprocess_uservec4_enable.integer)
909 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
911 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
912 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
913 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
916 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
917 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
918 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
920 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
921 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
923 shaderstaticparms_count = 0;
926 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
927 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
928 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
929 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
930 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
931 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
932 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
933 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
936 /// information about each possible shader permutation
937 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
938 /// currently selected permutation
939 r_glsl_permutation_t *r_glsl_permutation;
940 /// storage for permutations linked in the hash table
941 memexpandablearray_t r_glsl_permutationarray;
943 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
945 //unsigned int hashdepth = 0;
946 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
947 r_glsl_permutation_t *p;
948 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
950 if (p->mode == mode && p->permutation == permutation)
952 //if (hashdepth > 10)
953 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
958 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
960 p->permutation = permutation;
961 p->hashnext = r_glsl_permutationhash[mode][hashindex];
962 r_glsl_permutationhash[mode][hashindex] = p;
963 //if (hashdepth > 10)
964 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
971 if (!filename || !filename[0])
973 if (!strcmp(filename, "glsl/default.glsl"))
975 if (!glslshaderstring)
977 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978 if (glslshaderstring)
979 Con_DPrintf("Loading shaders from file %s...\n", filename);
981 glslshaderstring = (char *)builtinshaderstring;
983 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
984 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
987 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
990 if (printfromdisknotice)
991 Con_DPrintf("from disk %s... ", filename);
997 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1001 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1002 char *vertexstring, *geometrystring, *fragmentstring;
1003 char permutationname[256];
1004 int vertstrings_count = 0;
1005 int geomstrings_count = 0;
1006 int fragstrings_count = 0;
1007 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1016 permutationname[0] = 0;
1017 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1018 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1019 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1021 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1023 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1024 if(vid.support.gl20shaders130)
1026 vertstrings_list[vertstrings_count++] = "#version 130\n";
1027 geomstrings_list[geomstrings_count++] = "#version 130\n";
1028 fragstrings_list[fragstrings_count++] = "#version 130\n";
1029 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1030 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1031 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1034 // the first pretext is which type of shader to compile as
1035 // (later these will all be bound together as a program object)
1036 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1037 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1038 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1040 // the second pretext is the mode (for example a light source)
1041 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1042 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1043 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1044 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1046 // now add all the permutation pretexts
1047 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1049 if (permutation & (1<<i))
1051 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1052 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1053 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1054 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1058 // keep line numbers correct
1059 vertstrings_list[vertstrings_count++] = "\n";
1060 geomstrings_list[geomstrings_count++] = "\n";
1061 fragstrings_list[fragstrings_count++] = "\n";
1066 R_CompileShader_AddStaticParms(mode, permutation);
1067 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1068 vertstrings_count += shaderstaticparms_count;
1069 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070 geomstrings_count += shaderstaticparms_count;
1071 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072 fragstrings_count += shaderstaticparms_count;
1074 // now append the shader text itself
1075 vertstrings_list[vertstrings_count++] = vertexstring;
1076 geomstrings_list[geomstrings_count++] = geometrystring;
1077 fragstrings_list[fragstrings_count++] = fragmentstring;
1079 // if any sources were NULL, clear the respective list
1081 vertstrings_count = 0;
1082 if (!geometrystring)
1083 geomstrings_count = 0;
1084 if (!fragmentstring)
1085 fragstrings_count = 0;
1087 // compile the shader program
1088 if (vertstrings_count + geomstrings_count + fragstrings_count)
1089 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1093 qglUseProgram(p->program);CHECKGLERROR
1094 // look up all the uniform variable names we care about, so we don't
1095 // have to look them up every time we set them
1097 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1098 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1099 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1100 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1101 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1102 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1103 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1104 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1105 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1106 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1107 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1108 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1109 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1110 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1111 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1112 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1113 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1114 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1115 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1116 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1117 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1118 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1119 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1120 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1121 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1128 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1130 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1131 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1132 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1133 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1134 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1135 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1136 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1143 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1144 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1145 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1146 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1148 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1149 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1150 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1151 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1154 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1155 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1156 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1157 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1158 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1159 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1160 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1161 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1162 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1163 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1164 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1165 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1166 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1167 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1168 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1169 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1170 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1171 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1172 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1173 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1174 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1175 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1176 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1177 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1178 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1179 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1180 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1181 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1182 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1183 // initialize the samplers to refer to the texture units we use
1184 p->tex_Texture_First = -1;
1185 p->tex_Texture_Second = -1;
1186 p->tex_Texture_GammaRamps = -1;
1187 p->tex_Texture_Normal = -1;
1188 p->tex_Texture_Color = -1;
1189 p->tex_Texture_Gloss = -1;
1190 p->tex_Texture_Glow = -1;
1191 p->tex_Texture_SecondaryNormal = -1;
1192 p->tex_Texture_SecondaryColor = -1;
1193 p->tex_Texture_SecondaryGloss = -1;
1194 p->tex_Texture_SecondaryGlow = -1;
1195 p->tex_Texture_Pants = -1;
1196 p->tex_Texture_Shirt = -1;
1197 p->tex_Texture_FogHeightTexture = -1;
1198 p->tex_Texture_FogMask = -1;
1199 p->tex_Texture_Lightmap = -1;
1200 p->tex_Texture_Deluxemap = -1;
1201 p->tex_Texture_Attenuation = -1;
1202 p->tex_Texture_Cube = -1;
1203 p->tex_Texture_Refraction = -1;
1204 p->tex_Texture_Reflection = -1;
1205 p->tex_Texture_ShadowMap2D = -1;
1206 p->tex_Texture_CubeProjection = -1;
1207 p->tex_Texture_ScreenDepth = -1;
1208 p->tex_Texture_ScreenNormalMap = -1;
1209 p->tex_Texture_ScreenDiffuse = -1;
1210 p->tex_Texture_ScreenSpecular = -1;
1211 p->tex_Texture_ReflectMask = -1;
1212 p->tex_Texture_ReflectCube = -1;
1213 p->tex_Texture_BounceGrid = -1;
1215 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1216 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1217 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1218 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1219 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1220 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1221 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1222 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1224 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1225 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1226 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1227 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1228 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1230 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1231 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1232 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1233 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1234 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1235 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1236 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1237 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1238 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1239 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1240 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1241 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1242 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1243 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1244 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1246 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1249 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1253 Mem_Free(vertexstring);
1255 Mem_Free(geometrystring);
1257 Mem_Free(fragmentstring);
1260 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1262 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1263 if (r_glsl_permutation != perm)
1265 r_glsl_permutation = perm;
1266 if (!r_glsl_permutation->program)
1268 if (!r_glsl_permutation->compiled)
1269 R_GLSL_CompilePermutation(perm, mode, permutation);
1270 if (!r_glsl_permutation->program)
1272 // remove features until we find a valid permutation
1274 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1276 // reduce i more quickly whenever it would not remove any bits
1277 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1278 if (!(permutation & j))
1281 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282 if (!r_glsl_permutation->compiled)
1283 R_GLSL_CompilePermutation(perm, mode, permutation);
1284 if (r_glsl_permutation->program)
1287 if (i >= SHADERPERMUTATION_COUNT)
1289 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1290 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291 qglUseProgram(0);CHECKGLERROR
1292 return; // no bit left to clear, entire mode is broken
1297 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1299 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1300 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1301 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1308 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1309 extern D3DCAPS9 vid_d3d9caps;
1312 struct r_hlsl_permutation_s;
1313 typedef struct r_hlsl_permutation_s
1315 /// hash lookup data
1316 struct r_hlsl_permutation_s *hashnext;
1318 unsigned int permutation;
1320 /// indicates if we have tried compiling this permutation already
1322 /// NULL if compilation failed
1323 IDirect3DVertexShader9 *vertexshader;
1324 IDirect3DPixelShader9 *pixelshader;
1326 r_hlsl_permutation_t;
1328 typedef enum D3DVSREGISTER_e
1330 D3DVSREGISTER_TexMatrix = 0, // float4x4
1331 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1332 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1333 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1334 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1335 D3DVSREGISTER_ModelToLight = 20, // float4x4
1336 D3DVSREGISTER_EyePosition = 24,
1337 D3DVSREGISTER_FogPlane = 25,
1338 D3DVSREGISTER_LightDir = 26,
1339 D3DVSREGISTER_LightPosition = 27,
1343 typedef enum D3DPSREGISTER_e
1345 D3DPSREGISTER_Alpha = 0,
1346 D3DPSREGISTER_BloomBlur_Parameters = 1,
1347 D3DPSREGISTER_ClientTime = 2,
1348 D3DPSREGISTER_Color_Ambient = 3,
1349 D3DPSREGISTER_Color_Diffuse = 4,
1350 D3DPSREGISTER_Color_Specular = 5,
1351 D3DPSREGISTER_Color_Glow = 6,
1352 D3DPSREGISTER_Color_Pants = 7,
1353 D3DPSREGISTER_Color_Shirt = 8,
1354 D3DPSREGISTER_DeferredColor_Ambient = 9,
1355 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1356 D3DPSREGISTER_DeferredColor_Specular = 11,
1357 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1358 D3DPSREGISTER_DeferredMod_Specular = 13,
1359 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1360 D3DPSREGISTER_EyePosition = 15, // unused
1361 D3DPSREGISTER_FogColor = 16,
1362 D3DPSREGISTER_FogHeightFade = 17,
1363 D3DPSREGISTER_FogPlane = 18,
1364 D3DPSREGISTER_FogPlaneViewDist = 19,
1365 D3DPSREGISTER_FogRangeRecip = 20,
1366 D3DPSREGISTER_LightColor = 21,
1367 D3DPSREGISTER_LightDir = 22, // unused
1368 D3DPSREGISTER_LightPosition = 23,
1369 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1370 D3DPSREGISTER_PixelSize = 25,
1371 D3DPSREGISTER_ReflectColor = 26,
1372 D3DPSREGISTER_ReflectFactor = 27,
1373 D3DPSREGISTER_ReflectOffset = 28,
1374 D3DPSREGISTER_RefractColor = 29,
1375 D3DPSREGISTER_Saturation = 30,
1376 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1377 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1378 D3DPSREGISTER_ScreenToDepth = 33,
1379 D3DPSREGISTER_ShadowMap_Parameters = 34,
1380 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1381 D3DPSREGISTER_SpecularPower = 36,
1382 D3DPSREGISTER_UserVec1 = 37,
1383 D3DPSREGISTER_UserVec2 = 38,
1384 D3DPSREGISTER_UserVec3 = 39,
1385 D3DPSREGISTER_UserVec4 = 40,
1386 D3DPSREGISTER_ViewTintColor = 41,
1387 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1388 D3DPSREGISTER_BloomColorSubtract = 43,
1389 D3DPSREGISTER_ViewToLight = 44, // float4x4
1390 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1391 D3DPSREGISTER_NormalmapScrollBlend = 52,
1392 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1406 //unsigned int hashdepth = 0;
1407 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408 r_hlsl_permutation_t *p;
1409 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1411 if (p->mode == mode && p->permutation == permutation)
1413 //if (hashdepth > 10)
1414 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1419 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1421 p->permutation = permutation;
1422 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423 r_hlsl_permutationhash[mode][hashindex] = p;
1424 //if (hashdepth > 10)
1425 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1432 if (!filename || !filename[0])
1434 if (!strcmp(filename, "hlsl/default.hlsl"))
1436 if (!hlslshaderstring)
1438 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439 if (hlslshaderstring)
1440 Con_DPrintf("Loading shaders from file %s...\n", filename);
1442 hlslshaderstring = (char *)builtinhlslshaderstring;
1444 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446 return shaderstring;
1448 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1451 if (printfromdisknotice)
1452 Con_DPrintf("from disk %s... ", filename);
1453 return shaderstring;
1455 return shaderstring;
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1464 DWORD *vsbin = NULL;
1465 DWORD *psbin = NULL;
1466 fs_offset_t vsbinsize;
1467 fs_offset_t psbinsize;
1468 // IDirect3DVertexShader9 *vs = NULL;
1469 // IDirect3DPixelShader9 *ps = NULL;
1470 ID3DXBuffer *vslog = NULL;
1471 ID3DXBuffer *vsbuffer = NULL;
1472 ID3DXConstantTable *vsconstanttable = NULL;
1473 ID3DXBuffer *pslog = NULL;
1474 ID3DXBuffer *psbuffer = NULL;
1475 ID3DXConstantTable *psconstanttable = NULL;
1478 char temp[MAX_INPUTLINE];
1479 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480 qboolean debugshader = gl_paranoid.integer != 0;
1481 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1482 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1486 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1488 if ((!vsbin && vertstring) || (!psbin && fragstring))
1490 const char* dllnames_d3dx9 [] =
1514 dllhandle_t d3dx9_dll = NULL;
1515 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1516 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1517 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518 dllfunction_t d3dx9_dllfuncs[] =
1520 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1521 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1522 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1525 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1527 DWORD shaderflags = 0;
1529 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1530 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1531 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1532 if (vertstring && vertstring[0])
1536 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1537 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1538 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1539 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1542 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1545 vsbinsize = vsbuffer->GetBufferSize();
1546 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1547 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1548 vsbuffer->Release();
1552 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1553 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1557 if (fragstring && fragstring[0])
1561 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1562 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1563 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1564 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570 psbinsize = psbuffer->GetBufferSize();
1571 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1572 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1573 psbuffer->Release();
1577 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1578 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1582 Sys_UnloadLibrary(&d3dx9_dll);
1585 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1589 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1590 if (FAILED(vsresult))
1591 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1592 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1593 if (FAILED(psresult))
1594 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1596 // free the shader data
1597 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1598 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1601 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1604 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1605 int vertstring_length = 0;
1606 int geomstring_length = 0;
1607 int fragstring_length = 0;
1609 char *vertexstring, *geometrystring, *fragmentstring;
1610 char *vertstring, *geomstring, *fragstring;
1611 char permutationname[256];
1612 char cachename[256];
1613 int vertstrings_count = 0;
1614 int geomstrings_count = 0;
1615 int fragstrings_count = 0;
1616 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1617 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1618 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1623 p->vertexshader = NULL;
1624 p->pixelshader = NULL;
1626 permutationname[0] = 0;
1628 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1629 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1630 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1632 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1633 strlcat(cachename, "hlsl/", sizeof(cachename));
1635 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1636 vertstrings_count = 0;
1637 geomstrings_count = 0;
1638 fragstrings_count = 0;
1639 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1640 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1641 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1643 // the first pretext is which type of shader to compile as
1644 // (later these will all be bound together as a program object)
1645 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1646 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1647 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1649 // the second pretext is the mode (for example a light source)
1650 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1651 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1652 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1653 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1654 strlcat(cachename, modeinfo->name, sizeof(cachename));
1656 // now add all the permutation pretexts
1657 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1659 if (permutation & (1<<i))
1661 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1662 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1663 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1664 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1665 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1669 // keep line numbers correct
1670 vertstrings_list[vertstrings_count++] = "\n";
1671 geomstrings_list[geomstrings_count++] = "\n";
1672 fragstrings_list[fragstrings_count++] = "\n";
1677 R_CompileShader_AddStaticParms(mode, permutation);
1678 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1679 vertstrings_count += shaderstaticparms_count;
1680 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681 geomstrings_count += shaderstaticparms_count;
1682 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683 fragstrings_count += shaderstaticparms_count;
1685 // replace spaces in the cachename with _ characters
1686 for (i = 0;cachename[i];i++)
1687 if (cachename[i] == ' ')
1690 // now append the shader text itself
1691 vertstrings_list[vertstrings_count++] = vertexstring;
1692 geomstrings_list[geomstrings_count++] = geometrystring;
1693 fragstrings_list[fragstrings_count++] = fragmentstring;
1695 // if any sources were NULL, clear the respective list
1697 vertstrings_count = 0;
1698 if (!geometrystring)
1699 geomstrings_count = 0;
1700 if (!fragmentstring)
1701 fragstrings_count = 0;
1703 vertstring_length = 0;
1704 for (i = 0;i < vertstrings_count;i++)
1705 vertstring_length += strlen(vertstrings_list[i]);
1706 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1707 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1708 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1710 geomstring_length = 0;
1711 for (i = 0;i < geomstrings_count;i++)
1712 geomstring_length += strlen(geomstrings_list[i]);
1713 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1714 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1715 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1717 fragstring_length = 0;
1718 for (i = 0;i < fragstrings_count;i++)
1719 fragstring_length += strlen(fragstrings_list[i]);
1720 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1721 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1722 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1724 // try to load the cached shader, or generate one
1725 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1727 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1728 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1730 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1734 Mem_Free(vertstring);
1736 Mem_Free(geomstring);
1738 Mem_Free(fragstring);
1740 Mem_Free(vertexstring);
1742 Mem_Free(geometrystring);
1744 Mem_Free(fragmentstring);
1747 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1748 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1749 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1750 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1751 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1752 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1754 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1757 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1758 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1759 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1761 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1763 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1764 if (r_hlsl_permutation != perm)
1766 r_hlsl_permutation = perm;
1767 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1769 if (!r_hlsl_permutation->compiled)
1770 R_HLSL_CompilePermutation(perm, mode, permutation);
1771 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773 // remove features until we find a valid permutation
1775 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777 // reduce i more quickly whenever it would not remove any bits
1778 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1779 if (!(permutation & j))
1782 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783 if (!r_hlsl_permutation->compiled)
1784 R_HLSL_CompilePermutation(perm, mode, permutation);
1785 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1788 if (i >= SHADERPERMUTATION_COUNT)
1790 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1791 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1792 return; // no bit left to clear, entire mode is broken
1796 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1797 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1799 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1800 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1801 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1805 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1807 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1808 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1809 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1810 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1813 void R_GLSL_Restart_f(void)
1815 unsigned int i, limit;
1816 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1817 Mem_Free(glslshaderstring);
1818 glslshaderstring = NULL;
1819 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1820 Mem_Free(hlslshaderstring);
1821 hlslshaderstring = NULL;
1822 switch(vid.renderpath)
1824 case RENDERPATH_D3D9:
1827 r_hlsl_permutation_t *p;
1828 r_hlsl_permutation = NULL;
1829 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1830 for (i = 0;i < limit;i++)
1832 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1834 if (p->vertexshader)
1835 IDirect3DVertexShader9_Release(p->vertexshader);
1837 IDirect3DPixelShader9_Release(p->pixelshader);
1838 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1841 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1845 case RENDERPATH_D3D10:
1846 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1848 case RENDERPATH_D3D11:
1849 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851 case RENDERPATH_GL20:
1852 case RENDERPATH_GLES2:
1854 r_glsl_permutation_t *p;
1855 r_glsl_permutation = NULL;
1856 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1857 for (i = 0;i < limit;i++)
1859 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1861 GL_Backend_FreeProgram(p->program);
1862 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868 case RENDERPATH_GL11:
1869 case RENDERPATH_GL13:
1870 case RENDERPATH_GLES1:
1872 case RENDERPATH_SOFT:
1877 void R_GLSL_DumpShader_f(void)
1882 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1885 FS_Print(file, "/* The engine may define the following macros:\n");
1886 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887 for (i = 0;i < SHADERMODE_COUNT;i++)
1888 FS_Print(file, glslshadermodeinfo[i].pretext);
1889 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890 FS_Print(file, shaderpermutationinfo[i].pretext);
1891 FS_Print(file, "*/\n");
1892 FS_Print(file, builtinshaderstring);
1894 Con_Printf("glsl/default.glsl written\n");
1897 Con_Printf("failed to write to glsl/default.glsl\n");
1899 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1902 FS_Print(file, "/* The engine may define the following macros:\n");
1903 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1904 for (i = 0;i < SHADERMODE_COUNT;i++)
1905 FS_Print(file, hlslshadermodeinfo[i].pretext);
1906 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1907 FS_Print(file, shaderpermutationinfo[i].pretext);
1908 FS_Print(file, "*/\n");
1909 FS_Print(file, builtinhlslshaderstring);
1911 Con_Printf("hlsl/default.hlsl written\n");
1914 Con_Printf("failed to write to hlsl/default.hlsl\n");
1917 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1919 unsigned int permutation = 0;
1920 if (r_trippy.integer && !notrippy)
1921 permutation |= SHADERPERMUTATION_TRIPPY;
1922 permutation |= SHADERPERMUTATION_VIEWTINT;
1924 permutation |= SHADERPERMUTATION_DIFFUSE;
1926 permutation |= SHADERPERMUTATION_SPECULAR;
1927 if (texturemode == GL_MODULATE)
1928 permutation |= SHADERPERMUTATION_COLORMAPPING;
1929 else if (texturemode == GL_ADD)
1930 permutation |= SHADERPERMUTATION_GLOW;
1931 else if (texturemode == GL_DECAL)
1932 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1933 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1934 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1936 texturemode = GL_MODULATE;
1937 if (vid.allowalphatocoverage)
1938 GL_AlphaToCoverage(false);
1939 switch (vid.renderpath)
1941 case RENDERPATH_D3D9:
1943 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1944 R_Mesh_TexBind(GL20TU_FIRST , first );
1945 R_Mesh_TexBind(GL20TU_SECOND, second);
1946 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1947 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1950 case RENDERPATH_D3D10:
1951 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953 case RENDERPATH_D3D11:
1954 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956 case RENDERPATH_GL20:
1957 case RENDERPATH_GLES2:
1958 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1959 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1960 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1961 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1962 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1964 case RENDERPATH_GL13:
1965 case RENDERPATH_GLES1:
1966 R_Mesh_TexBind(0, first );
1967 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1968 R_Mesh_TexBind(1, second);
1970 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1972 case RENDERPATH_GL11:
1973 R_Mesh_TexBind(0, first );
1975 case RENDERPATH_SOFT:
1976 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1977 R_Mesh_TexBind(GL20TU_FIRST , first );
1978 R_Mesh_TexBind(GL20TU_SECOND, second);
1983 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1985 unsigned int permutation = 0;
1986 if (r_trippy.integer && !notrippy)
1987 permutation |= SHADERPERMUTATION_TRIPPY;
1988 if (vid.allowalphatocoverage)
1989 GL_AlphaToCoverage(false);
1990 switch (vid.renderpath)
1992 case RENDERPATH_D3D9:
1994 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1997 case RENDERPATH_D3D10:
1998 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2000 case RENDERPATH_D3D11:
2001 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2003 case RENDERPATH_GL20:
2004 case RENDERPATH_GLES2:
2005 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2007 case RENDERPATH_GL13:
2008 case RENDERPATH_GLES1:
2009 R_Mesh_TexBind(0, 0);
2010 R_Mesh_TexBind(1, 0);
2012 case RENDERPATH_GL11:
2013 R_Mesh_TexBind(0, 0);
2015 case RENDERPATH_SOFT:
2016 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2023 int permutation = 0;
2024 if (r_trippy.integer && !notrippy)
2025 permutation |= SHADERPERMUTATION_TRIPPY;
2026 if (vid.allowalphatocoverage)
2027 GL_AlphaToCoverage(false);
2028 switch (vid.renderpath)
2030 case RENDERPATH_D3D9:
2032 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2035 case RENDERPATH_D3D10:
2036 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2038 case RENDERPATH_D3D11:
2039 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2041 case RENDERPATH_GL20:
2042 case RENDERPATH_GLES2:
2043 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2045 case RENDERPATH_GL13:
2046 case RENDERPATH_GLES1:
2048 case RENDERPATH_GL11:
2050 case RENDERPATH_SOFT:
2051 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern cvar_t r_shadow_deferred_8bitrange;
2058 extern rtexture_t *r_shadow_attenuationgradienttexture;
2059 extern rtexture_t *r_shadow_attenuation2dtexture;
2060 extern rtexture_t *r_shadow_attenuation3dtexture;
2061 extern qboolean r_shadow_usingshadowmap2d;
2062 extern qboolean r_shadow_usingshadowmaportho;
2063 extern float r_shadow_shadowmap_texturescale[2];
2064 extern float r_shadow_shadowmap_parameters[4];
2065 extern qboolean r_shadow_shadowmapvsdct;
2066 extern qboolean r_shadow_shadowmapsampler;
2067 extern int r_shadow_shadowmappcf;
2068 extern rtexture_t *r_shadow_shadowmap2dtexture;
2069 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2070 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2071 extern matrix4x4_t r_shadow_shadowmapmatrix;
2072 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2073 extern int r_shadow_prepass_width;
2074 extern int r_shadow_prepass_height;
2075 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2076 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2077 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2078 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2079 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2081 #define BLENDFUNC_ALLOWS_COLORMOD 1
2082 #define BLENDFUNC_ALLOWS_FOG 2
2083 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2084 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2085 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2086 static int R_BlendFuncFlags(int src, int dst)
2090 // a blendfunc allows colormod if:
2091 // a) it can never keep the destination pixel invariant, or
2092 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2093 // this is to prevent unintended side effects from colormod
2095 // a blendfunc allows fog if:
2096 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2097 // this is to prevent unintended side effects from fog
2099 // these checks are the output of fogeval.pl
2101 r |= BLENDFUNC_ALLOWS_COLORMOD;
2102 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2106 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2111 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2112 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2115 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2122 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2129 // select a permutation of the lighting shader appropriate to this
2130 // combination of texture, entity, light source, and fogging, only use the
2131 // minimum features necessary to avoid wasting rendering time in the
2132 // fragment shader on features that are not being used
2133 unsigned int permutation = 0;
2134 unsigned int mode = 0;
2136 static float dummy_colormod[3] = {1, 1, 1};
2137 float *colormod = rsurface.colormod;
2139 matrix4x4_t tempmatrix;
2140 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2141 if (r_trippy.integer && !notrippy)
2142 permutation |= SHADERPERMUTATION_TRIPPY;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2144 permutation |= SHADERPERMUTATION_ALPHAKILL;
2145 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2146 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2147 if (rsurfacepass == RSURFPASS_BACKGROUND)
2149 // distorted background
2150 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2152 mode = SHADERMODE_WATER;
2153 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2155 // this is the right thing to do for wateralpha
2156 GL_BlendFunc(GL_ONE, GL_ZERO);
2157 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2161 // this is the right thing to do for entity alpha
2162 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2166 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2168 mode = SHADERMODE_REFRACTION;
2169 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2174 mode = SHADERMODE_GENERIC;
2175 permutation |= SHADERPERMUTATION_DIFFUSE;
2176 GL_BlendFunc(GL_ONE, GL_ZERO);
2177 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2179 if (vid.allowalphatocoverage)
2180 GL_AlphaToCoverage(false);
2182 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2184 if (r_glsl_offsetmapping.integer)
2186 switch(rsurface.texture->offsetmapping)
2188 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2189 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191 case OFFSETMAPPING_OFF: break;
2194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196 // normalmap (deferred prepass), may use alpha test on diffuse
2197 mode = SHADERMODE_DEFERREDGEOMETRY;
2198 GL_BlendFunc(GL_ONE, GL_ZERO);
2199 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2200 if (vid.allowalphatocoverage)
2201 GL_AlphaToCoverage(false);
2203 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2205 if (r_glsl_offsetmapping.integer)
2207 switch(rsurface.texture->offsetmapping)
2209 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2210 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2212 case OFFSETMAPPING_OFF: break;
2215 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2216 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2218 mode = SHADERMODE_LIGHTSOURCE;
2219 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2220 permutation |= SHADERPERMUTATION_CUBEFILTER;
2221 if (diffusescale > 0)
2222 permutation |= SHADERPERMUTATION_DIFFUSE;
2223 if (specularscale > 0)
2224 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2225 if (r_refdef.fogenabled)
2226 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2227 if (rsurface.texture->colormapping)
2228 permutation |= SHADERPERMUTATION_COLORMAPPING;
2229 if (r_shadow_usingshadowmap2d)
2231 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2232 if(r_shadow_shadowmapvsdct)
2233 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2235 if (r_shadow_shadowmapsampler)
2236 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2237 if (r_shadow_shadowmappcf > 1)
2238 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2239 else if (r_shadow_shadowmappcf)
2240 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2242 if (rsurface.texture->reflectmasktexture)
2243 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2244 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2245 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2246 if (vid.allowalphatocoverage)
2247 GL_AlphaToCoverage(false);
2249 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2251 if (r_glsl_offsetmapping.integer)
2253 switch(rsurface.texture->offsetmapping)
2255 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258 case OFFSETMAPPING_OFF: break;
2261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263 // unshaded geometry (fullbright or ambient model lighting)
2264 mode = SHADERMODE_FLATCOLOR;
2265 ambientscale = diffusescale = specularscale = 0;
2266 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2267 permutation |= SHADERPERMUTATION_GLOW;
2268 if (r_refdef.fogenabled)
2269 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270 if (rsurface.texture->colormapping)
2271 permutation |= SHADERPERMUTATION_COLORMAPPING;
2272 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2274 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2277 if (r_shadow_shadowmapsampler)
2278 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279 if (r_shadow_shadowmappcf > 1)
2280 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281 else if (r_shadow_shadowmappcf)
2282 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2284 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285 permutation |= SHADERPERMUTATION_REFLECTION;
2286 if (rsurface.texture->reflectmasktexture)
2287 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2288 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2290 // when using alphatocoverage, we don't need alphakill
2291 if (vid.allowalphatocoverage)
2293 if (r_transparent_alphatocoverage.integer)
2295 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2296 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2299 GL_AlphaToCoverage(false);
2302 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2304 if (r_glsl_offsetmapping.integer)
2306 switch(rsurface.texture->offsetmapping)
2308 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2309 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2311 case OFFSETMAPPING_OFF: break;
2314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316 // directional model lighting
2317 mode = SHADERMODE_LIGHTDIRECTION;
2318 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319 permutation |= SHADERPERMUTATION_GLOW;
2320 permutation |= SHADERPERMUTATION_DIFFUSE;
2321 if (specularscale > 0)
2322 permutation |= SHADERPERMUTATION_SPECULAR;
2323 if (r_refdef.fogenabled)
2324 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2325 if (rsurface.texture->colormapping)
2326 permutation |= SHADERPERMUTATION_COLORMAPPING;
2327 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2329 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2330 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2332 if (r_shadow_shadowmapsampler)
2333 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2334 if (r_shadow_shadowmappcf > 1)
2335 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2336 else if (r_shadow_shadowmappcf)
2337 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2339 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2340 permutation |= SHADERPERMUTATION_REFLECTION;
2341 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2342 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2343 if (rsurface.texture->reflectmasktexture)
2344 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2345 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2347 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2348 if (r_shadow_bouncegriddirectional)
2349 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2351 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353 // when using alphatocoverage, we don't need alphakill
2354 if (vid.allowalphatocoverage)
2356 if (r_transparent_alphatocoverage.integer)
2358 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2359 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2362 GL_AlphaToCoverage(false);
2365 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2367 if (r_glsl_offsetmapping.integer)
2369 switch(rsurface.texture->offsetmapping)
2371 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2372 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374 case OFFSETMAPPING_OFF: break;
2377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2378 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379 // ambient model lighting
2380 mode = SHADERMODE_LIGHTDIRECTION;
2381 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2382 permutation |= SHADERPERMUTATION_GLOW;
2383 if (r_refdef.fogenabled)
2384 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2385 if (rsurface.texture->colormapping)
2386 permutation |= SHADERPERMUTATION_COLORMAPPING;
2387 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2389 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2390 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2392 if (r_shadow_shadowmapsampler)
2393 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2394 if (r_shadow_shadowmappcf > 1)
2395 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2396 else if (r_shadow_shadowmappcf)
2397 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2399 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2400 permutation |= SHADERPERMUTATION_REFLECTION;
2401 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2402 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2403 if (rsurface.texture->reflectmasktexture)
2404 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2405 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2407 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2408 if (r_shadow_bouncegriddirectional)
2409 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2411 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413 // when using alphatocoverage, we don't need alphakill
2414 if (vid.allowalphatocoverage)
2416 if (r_transparent_alphatocoverage.integer)
2418 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2419 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422 GL_AlphaToCoverage(false);
2427 if (r_glsl_offsetmapping.integer)
2429 switch(rsurface.texture->offsetmapping)
2431 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2432 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434 case OFFSETMAPPING_OFF: break;
2437 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2438 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2440 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2441 permutation |= SHADERPERMUTATION_GLOW;
2442 if (r_refdef.fogenabled)
2443 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2444 if (rsurface.texture->colormapping)
2445 permutation |= SHADERPERMUTATION_COLORMAPPING;
2446 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2448 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2449 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2451 if (r_shadow_shadowmapsampler)
2452 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2453 if (r_shadow_shadowmappcf > 1)
2454 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2455 else if (r_shadow_shadowmappcf)
2456 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2458 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459 permutation |= SHADERPERMUTATION_REFLECTION;
2460 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462 if (rsurface.texture->reflectmasktexture)
2463 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464 if (FAKELIGHT_ENABLED)
2466 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467 mode = SHADERMODE_FAKELIGHT;
2468 permutation |= SHADERPERMUTATION_DIFFUSE;
2469 if (specularscale > 0)
2470 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2474 // deluxemapping (light direction texture)
2475 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2478 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479 permutation |= SHADERPERMUTATION_DIFFUSE;
2480 if (specularscale > 0)
2481 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483 else if (r_glsl_deluxemapping.integer >= 2)
2485 // fake deluxemapping (uniform light direction in tangentspace)
2486 if (rsurface.uselightmaptexture)
2487 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2489 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490 permutation |= SHADERPERMUTATION_DIFFUSE;
2491 if (specularscale > 0)
2492 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2494 else if (rsurface.uselightmaptexture)
2496 // ordinary lightmapping (q1bsp, q3bsp)
2497 mode = SHADERMODE_LIGHTMAP;
2501 // ordinary vertex coloring (q3bsp)
2502 mode = SHADERMODE_VERTEXCOLOR;
2504 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2506 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507 if (r_shadow_bouncegriddirectional)
2508 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2510 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512 // when using alphatocoverage, we don't need alphakill
2513 if (vid.allowalphatocoverage)
2515 if (r_transparent_alphatocoverage.integer)
2517 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2521 GL_AlphaToCoverage(false);
2524 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525 colormod = dummy_colormod;
2526 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530 switch(vid.renderpath)
2532 case RENDERPATH_D3D9:
2534 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2535 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538 if (mode == SHADERMODE_LIGHTSOURCE)
2540 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2545 if (mode == SHADERMODE_LIGHTDIRECTION)
2547 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2550 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2556 if (mode == SHADERMODE_LIGHTSOURCE)
2558 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2564 // additive passes are only darkened by fog, not tinted
2565 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2570 if (mode == SHADERMODE_FLATCOLOR)
2572 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2574 else if (mode == SHADERMODE_LIGHTDIRECTION)
2576 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2578 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2579 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2580 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2581 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2586 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2589 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2590 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2592 // additive passes are only darkened by fog, not tinted
2593 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2596 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2598 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2599 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2600 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605 if (mode == SHADERMODE_WATER)
2606 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2608 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2612 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613 if (rsurface.texture->pantstexture)
2614 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2616 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617 if (rsurface.texture->shirttexture)
2618 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2620 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2631 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2632 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2633 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2635 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2636 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2637 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2638 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2639 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2640 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2641 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2642 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2643 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2644 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2645 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2646 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2647 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2648 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2649 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2650 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2651 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2652 if (rsurfacepass == RSURFPASS_BACKGROUND)
2654 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2655 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2656 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2660 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2663 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2664 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2665 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2666 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2668 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2669 if (rsurface.rtlight)
2671 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2672 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2677 case RENDERPATH_D3D10:
2678 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2680 case RENDERPATH_D3D11:
2681 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683 case RENDERPATH_GL20:
2684 case RENDERPATH_GLES2:
2685 if (!vid.useinterleavedarrays)
2687 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2688 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2698 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2699 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2701 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703 if (mode == SHADERMODE_LIGHTSOURCE)
2705 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2712 // additive passes are only darkened by fog, not tinted
2713 if (r_glsl_permutation->loc_FogColor >= 0)
2714 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2719 if (mode == SHADERMODE_FLATCOLOR)
2721 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2723 else if (mode == SHADERMODE_LIGHTDIRECTION)
2725 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2726 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2727 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2728 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2729 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2730 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2731 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2735 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2736 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2737 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2738 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2739 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2741 // additive passes are only darkened by fog, not tinted
2742 if (r_glsl_permutation->loc_FogColor >= 0)
2744 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2747 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2749 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2750 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2751 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2752 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2753 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2754 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2757 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2759 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2763 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2765 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2767 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768 if (r_glsl_permutation->loc_Color_Pants >= 0)
2770 if (rsurface.texture->pantstexture)
2771 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2773 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2775 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2777 if (rsurface.texture->shirttexture)
2778 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2780 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2782 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2783 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2792 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2793 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2794 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2795 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2796 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2798 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2799 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2800 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2801 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2802 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2803 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2804 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2805 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2806 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2807 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2808 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2809 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2810 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2811 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2812 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2813 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2814 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2815 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2816 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2817 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2818 if (rsurfacepass == RSURFPASS_BACKGROUND)
2820 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2821 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2822 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2826 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2828 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2829 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2830 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2831 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2832 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2834 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2835 if (rsurface.rtlight)
2837 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2838 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2841 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2844 case RENDERPATH_GL11:
2845 case RENDERPATH_GL13:
2846 case RENDERPATH_GLES1:
2848 case RENDERPATH_SOFT:
2849 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2850 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851 R_SetupShader_SetPermutationSoft(mode, permutation);
2852 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853 if (mode == SHADERMODE_LIGHTSOURCE)
2855 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2862 // additive passes are only darkened by fog, not tinted
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2868 if (mode == SHADERMODE_FLATCOLOR)
2870 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2872 else if (mode == SHADERMODE_LIGHTDIRECTION)
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2875 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2876 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2878 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2879 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2890 // additive passes are only darkened by fog, not tinted
2891 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2896 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2897 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2898 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2899 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2900 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2903 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2905 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2911 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2913 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916 if (rsurface.texture->pantstexture)
2917 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2919 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923 if (rsurface.texture->shirttexture)
2924 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2926 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2941 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2942 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2943 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2944 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2945 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2946 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2947 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2948 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2949 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2950 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2951 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2952 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2953 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2954 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2955 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2956 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2957 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2958 if (rsurfacepass == RSURFPASS_BACKGROUND)
2960 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2961 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2962 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2968 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2969 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2970 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2971 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2972 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2974 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2975 if (rsurface.rtlight)
2977 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2978 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2985 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2987 // select a permutation of the lighting shader appropriate to this
2988 // combination of texture, entity, light source, and fogging, only use the
2989 // minimum features necessary to avoid wasting rendering time in the
2990 // fragment shader on features that are not being used
2991 unsigned int permutation = 0;
2992 unsigned int mode = 0;
2993 const float *lightcolorbase = rtlight->currentcolor;
2994 float ambientscale = rtlight->ambientscale;
2995 float diffusescale = rtlight->diffusescale;
2996 float specularscale = rtlight->specularscale;
2997 // this is the location of the light in view space
2998 vec3_t viewlightorigin;
2999 // this transforms from view space (camera) to light space (cubemap)
3000 matrix4x4_t viewtolight;
3001 matrix4x4_t lighttoview;
3002 float viewtolight16f[16];
3003 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3005 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006 if (rtlight->currentcubemap != r_texture_whitecube)
3007 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008 if (diffusescale > 0)
3009 permutation |= SHADERPERMUTATION_DIFFUSE;
3010 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012 if (r_shadow_usingshadowmap2d)
3014 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015 if (r_shadow_shadowmapvsdct)
3016 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018 if (r_shadow_shadowmapsampler)
3019 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3020 if (r_shadow_shadowmappcf > 1)
3021 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3022 else if (r_shadow_shadowmappcf)
3023 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3025 if (vid.allowalphatocoverage)
3026 GL_AlphaToCoverage(false);
3027 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3028 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3029 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3030 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3031 switch(vid.renderpath)
3033 case RENDERPATH_D3D9:
3035 R_SetupShader_SetPermutationHLSL(mode, permutation);
3036 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3037 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3038 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3039 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3040 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3041 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3042 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3043 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, ((r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3044 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3045 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3047 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3048 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3049 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3050 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3051 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3052 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3055 case RENDERPATH_D3D10:
3056 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3058 case RENDERPATH_D3D11:
3059 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3061 case RENDERPATH_GL20:
3062 case RENDERPATH_GLES2:
3063 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3065 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3066 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3067 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3068 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3069 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3070 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3071 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , ((r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3072 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f( r_glsl_permutation->loc_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3073 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3075 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3076 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3077 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3078 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3079 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3080 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3082 case RENDERPATH_GL11:
3083 case RENDERPATH_GL13:
3084 case RENDERPATH_GLES1:
3086 case RENDERPATH_SOFT:
3087 R_SetupShader_SetPermutationGLSL(mode, permutation);
3088 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3089 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3090 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3091 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3092 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3093 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3094 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3095 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , ((r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3096 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3097 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3099 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3100 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3101 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3102 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3103 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3104 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3109 #define SKINFRAME_HASH 1024
3113 int loadsequence; // incremented each level change
3114 memexpandablearray_t array;
3115 skinframe_t *hash[SKINFRAME_HASH];
3118 r_skinframe_t r_skinframe;
3120 void R_SkinFrame_PrepareForPurge(void)
3122 r_skinframe.loadsequence++;
3123 // wrap it without hitting zero
3124 if (r_skinframe.loadsequence >= 200)
3125 r_skinframe.loadsequence = 1;
3128 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3132 // mark the skinframe as used for the purging code
3133 skinframe->loadsequence = r_skinframe.loadsequence;
3136 void R_SkinFrame_Purge(void)
3140 for (i = 0;i < SKINFRAME_HASH;i++)
3142 for (s = r_skinframe.hash[i];s;s = s->next)
3144 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3146 if (s->merged == s->base)
3148 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3149 R_PurgeTexture(s->stain );s->stain = NULL;
3150 R_PurgeTexture(s->merged);s->merged = NULL;
3151 R_PurgeTexture(s->base );s->base = NULL;
3152 R_PurgeTexture(s->pants );s->pants = NULL;
3153 R_PurgeTexture(s->shirt );s->shirt = NULL;
3154 R_PurgeTexture(s->nmap );s->nmap = NULL;
3155 R_PurgeTexture(s->gloss );s->gloss = NULL;
3156 R_PurgeTexture(s->glow );s->glow = NULL;
3157 R_PurgeTexture(s->fog );s->fog = NULL;
3158 R_PurgeTexture(s->reflect);s->reflect = NULL;
3159 s->loadsequence = 0;
3165 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3167 char basename[MAX_QPATH];
3169 Image_StripImageExtension(name, basename, sizeof(basename));
3171 if( last == NULL ) {
3173 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3174 item = r_skinframe.hash[hashindex];
3179 // linearly search through the hash bucket
3180 for( ; item ; item = item->next ) {
3181 if( !strcmp( item->basename, basename ) ) {
3188 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3192 char basename[MAX_QPATH];
3194 Image_StripImageExtension(name, basename, sizeof(basename));
3196 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3197 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3198 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3202 rtexture_t *dyntexture;
3203 // check whether its a dynamic texture
3204 dyntexture = CL_GetDynTexture( basename );
3205 if (!add && !dyntexture)
3207 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3208 memset(item, 0, sizeof(*item));
3209 strlcpy(item->basename, basename, sizeof(item->basename));
3210 item->base = dyntexture; // either NULL or dyntexture handle
3211 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3212 item->comparewidth = comparewidth;
3213 item->compareheight = compareheight;
3214 item->comparecrc = comparecrc;
3215 item->next = r_skinframe.hash[hashindex];
3216 r_skinframe.hash[hashindex] = item;
3218 else if (textureflags & TEXF_FORCE_RELOAD)
3220 rtexture_t *dyntexture;
3221 // check whether its a dynamic texture
3222 dyntexture = CL_GetDynTexture( basename );
3223 if (!add && !dyntexture)
3225 if (item->merged == item->base)
3226 item->merged = NULL;
3227 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3228 R_PurgeTexture(item->stain );item->stain = NULL;
3229 R_PurgeTexture(item->merged);item->merged = NULL;
3230 R_PurgeTexture(item->base );item->base = NULL;
3231 R_PurgeTexture(item->pants );item->pants = NULL;
3232 R_PurgeTexture(item->shirt );item->shirt = NULL;
3233 R_PurgeTexture(item->nmap );item->nmap = NULL;
3234 R_PurgeTexture(item->gloss );item->gloss = NULL;
3235 R_PurgeTexture(item->glow );item->glow = NULL;
3236 R_PurgeTexture(item->fog );item->fog = NULL;
3237 R_PurgeTexture(item->reflect);item->reflect = NULL;
3238 item->loadsequence = 0;
3240 else if( item->base == NULL )
3242 rtexture_t *dyntexture;
3243 // check whether its a dynamic texture
3244 // 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]
3245 dyntexture = CL_GetDynTexture( basename );
3246 item->base = dyntexture; // either NULL or dyntexture handle
3249 R_SkinFrame_MarkUsed(item);
3253 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3255 unsigned long long avgcolor[5], wsum; \
3263 for(pix = 0; pix < cnt; ++pix) \
3266 for(comp = 0; comp < 3; ++comp) \
3268 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3271 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3273 for(comp = 0; comp < 3; ++comp) \
3274 avgcolor[comp] += getpixel * w; \
3277 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3278 avgcolor[4] += getpixel; \
3280 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3282 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3283 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3284 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3285 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3288 extern cvar_t gl_picmip;
3289 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3292 unsigned char *pixels;
3293 unsigned char *bumppixels;
3294 unsigned char *basepixels = NULL;
3295 int basepixels_width = 0;
3296 int basepixels_height = 0;
3297 skinframe_t *skinframe;
3298 rtexture_t *ddsbase = NULL;
3299 qboolean ddshasalpha = false;
3300 float ddsavgcolor[4];
3301 char basename[MAX_QPATH];
3302 int miplevel = R_PicmipForFlags(textureflags);
3303 int savemiplevel = miplevel;
3306 if (cls.state == ca_dedicated)
3309 // return an existing skinframe if already loaded
3310 // if loading of the first image fails, don't make a new skinframe as it
3311 // would cause all future lookups of this to be missing
3312 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3313 if (skinframe && skinframe->base)
3316 Image_StripImageExtension(name, basename, sizeof(basename));
3318 // check for DDS texture file first
3319 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3321 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3322 if (basepixels == NULL)
3326 // FIXME handle miplevel
3328 if (developer_loading.integer)
3329 Con_Printf("loading skin \"%s\"\n", name);
3331 // we've got some pixels to store, so really allocate this new texture now
3333 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3334 textureflags &= ~TEXF_FORCE_RELOAD;
3335 skinframe->stain = NULL;
3336 skinframe->merged = NULL;
3337 skinframe->base = NULL;
3338 skinframe->pants = NULL;
3339 skinframe->shirt = NULL;
3340 skinframe->nmap = NULL;
3341 skinframe->gloss = NULL;
3342 skinframe->glow = NULL;
3343 skinframe->fog = NULL;
3344 skinframe->reflect = NULL;
3345 skinframe->hasalpha = false;
3349 skinframe->base = ddsbase;
3350 skinframe->hasalpha = ddshasalpha;
3351 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3352 if (r_loadfog && skinframe->hasalpha)
3353 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3354 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3358 basepixels_width = image_width;
3359 basepixels_height = image_height;
3360 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);
3361 if (textureflags & TEXF_ALPHA)
3363 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3365 if (basepixels[j] < 255)
3367 skinframe->hasalpha = true;
3371 if (r_loadfog && skinframe->hasalpha)
3373 // has transparent pixels
3374 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3375 for (j = 0;j < image_width * image_height * 4;j += 4)
3380 pixels[j+3] = basepixels[j+3];
3382 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);
3386 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3388 //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]);
3389 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3390 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3391 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3392 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3398 mymiplevel = savemiplevel;
3399 if (r_loadnormalmap)
3400 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);
3401 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3403 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3404 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3405 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3406 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3409 // _norm is the name used by tenebrae and has been adopted as standard
3410 if (r_loadnormalmap && skinframe->nmap == NULL)
3412 mymiplevel = savemiplevel;
3413 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3415 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);
3419 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3421 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3422 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3423 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3425 Mem_Free(bumppixels);
3427 else if (r_shadow_bumpscale_basetexture.value > 0)
3429 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3430 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3431 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);
3435 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3436 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440 // _luma is supported only for tenebrae compatibility
3441 // _glow is the preferred name
3442 mymiplevel = savemiplevel;
3443 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))))
3445 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);
3447 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3448 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3450 Mem_Free(pixels);pixels = NULL;
3453 mymiplevel = savemiplevel;
3454 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3456 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);
3458 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3459 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3465 mymiplevel = savemiplevel;
3466 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3468 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);
3470 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3471 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3477 mymiplevel = savemiplevel;
3478 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3480 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);
3482 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3483 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3489 mymiplevel = savemiplevel;
3490 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3492 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);
3494 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3495 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3502 Mem_Free(basepixels);
3507 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3508 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3511 unsigned char *temp1, *temp2;
3512 skinframe_t *skinframe;
3514 if (cls.state == ca_dedicated)
3517 // if already loaded just return it, otherwise make a new skinframe
3518 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3519 if (skinframe && skinframe->base)
3521 textureflags &= ~TEXF_FORCE_RELOAD;
3523 skinframe->stain = NULL;
3524 skinframe->merged = NULL;
3525 skinframe->base = NULL;
3526 skinframe->pants = NULL;
3527 skinframe->shirt = NULL;
3528 skinframe->nmap = NULL;
3529 skinframe->gloss = NULL;
3530 skinframe->glow = NULL;
3531 skinframe->fog = NULL;
3532 skinframe->reflect = NULL;
3533 skinframe->hasalpha = false;
3535 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3539 if (developer_loading.integer)
3540 Con_Printf("loading 32bit skin \"%s\"\n", name);
3542 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3544 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3545 temp2 = temp1 + width * height * 4;
3546 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3547 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);
3550 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3551 if (textureflags & TEXF_ALPHA)
3553 for (i = 3;i < width * height * 4;i += 4)
3555 if (skindata[i] < 255)
3557 skinframe->hasalpha = true;
3561 if (r_loadfog && skinframe->hasalpha)
3563 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3564 memcpy(fogpixels, skindata, width * height * 4);
3565 for (i = 0;i < width * height * 4;i += 4)
3566 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3567 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3568 Mem_Free(fogpixels);
3572 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3573 //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]);
3578 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3582 skinframe_t *skinframe;
3584 if (cls.state == ca_dedicated)
3587 // if already loaded just return it, otherwise make a new skinframe
3588 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3589 if (skinframe && skinframe->base)
3591 textureflags &= ~TEXF_FORCE_RELOAD;
3593 skinframe->stain = NULL;
3594 skinframe->merged = NULL;
3595 skinframe->base = NULL;
3596 skinframe->pants = NULL;
3597 skinframe->shirt = NULL;
3598 skinframe->nmap = NULL;
3599 skinframe->gloss = NULL;
3600 skinframe->glow = NULL;
3601 skinframe->fog = NULL;
3602 skinframe->reflect = NULL;
3603 skinframe->hasalpha = false;
3605 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3609 if (developer_loading.integer)
3610 Con_Printf("loading quake skin \"%s\"\n", name);
3612 // 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)
3613 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3614 memcpy(skinframe->qpixels, skindata, width*height);
3615 skinframe->qwidth = width;
3616 skinframe->qheight = height;
3619 for (i = 0;i < width * height;i++)
3620 featuresmask |= palette_featureflags[skindata[i]];
3622 skinframe->hasalpha = false;
3623 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3624 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3625 skinframe->qgeneratemerged = true;
3626 skinframe->qgeneratebase = skinframe->qhascolormapping;
3627 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3629 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3630 //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]);
3635 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3639 unsigned char *skindata;
3641 if (!skinframe->qpixels)
3644 if (!skinframe->qhascolormapping)
3645 colormapped = false;
3649 if (!skinframe->qgeneratebase)
3654 if (!skinframe->qgeneratemerged)
3658 width = skinframe->qwidth;
3659 height = skinframe->qheight;
3660 skindata = skinframe->qpixels;
3662 if (skinframe->qgeneratenmap)
3664 unsigned char *temp1, *temp2;
3665 skinframe->qgeneratenmap = false;
3666 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3667 temp2 = temp1 + width * height * 4;
3668 // use either a custom palette or the quake palette
3669 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3670 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3671 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);
3675 if (skinframe->qgenerateglow)
3677 skinframe->qgenerateglow = false;
3678 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
3683 skinframe->qgeneratebase = false;
3684 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);
3685 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);
3686 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);
3690 skinframe->qgeneratemerged = false;
3691 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);
3694 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3696 Mem_Free(skinframe->qpixels);
3697 skinframe->qpixels = NULL;
3701 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)
3704 skinframe_t *skinframe;
3706 if (cls.state == ca_dedicated)
3709 // if already loaded just return it, otherwise make a new skinframe
3710 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3711 if (skinframe && skinframe->base)
3713 textureflags &= ~TEXF_FORCE_RELOAD;
3715 skinframe->stain = NULL;
3716 skinframe->merged = NULL;
3717 skinframe->base = NULL;
3718 skinframe->pants = NULL;
3719 skinframe->shirt = NULL;
3720 skinframe->nmap = NULL;
3721 skinframe->gloss = NULL;
3722 skinframe->glow = NULL;
3723 skinframe->fog = NULL;
3724 skinframe->reflect = NULL;
3725 skinframe->hasalpha = false;
3727 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3731 if (developer_loading.integer)
3732 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3734 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3735 if (textureflags & TEXF_ALPHA)
3737 for (i = 0;i < width * height;i++)
3739 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3741 skinframe->hasalpha = true;
3745 if (r_loadfog && skinframe->hasalpha)
3746 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3749 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3750 //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]);
3755 skinframe_t *R_SkinFrame_LoadMissing(void)
3757 skinframe_t *skinframe;
3759 if (cls.state == ca_dedicated)
3762 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3763 skinframe->stain = NULL;
3764 skinframe->merged = NULL;
3765 skinframe->base = NULL;
3766 skinframe->pants = NULL;
3767 skinframe->shirt = NULL;
3768 skinframe->nmap = NULL;
3769 skinframe->gloss = NULL;
3770 skinframe->glow = NULL;
3771 skinframe->fog = NULL;
3772 skinframe->reflect = NULL;
3773 skinframe->hasalpha = false;
3775 skinframe->avgcolor[0] = rand() / RAND_MAX;
3776 skinframe->avgcolor[1] = rand() / RAND_MAX;
3777 skinframe->avgcolor[2] = rand() / RAND_MAX;
3778 skinframe->avgcolor[3] = 1;
3783 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3784 typedef struct suffixinfo_s
3787 qboolean flipx, flipy, flipdiagonal;
3790 static suffixinfo_t suffix[3][6] =
3793 {"px", false, false, false},
3794 {"nx", false, false, false},
3795 {"py", false, false, false},
3796 {"ny", false, false, false},
3797 {"pz", false, false, false},
3798 {"nz", false, false, false}
3801 {"posx", false, false, false},
3802 {"negx", false, false, false},
3803 {"posy", false, false, false},
3804 {"negy", false, false, false},
3805 {"posz", false, false, false},
3806 {"negz", false, false, false}
3809 {"rt", true, false, true},
3810 {"lf", false, true, true},
3811 {"ft", true, true, false},
3812 {"bk", false, false, false},
3813 {"up", true, false, true},
3814 {"dn", true, false, true}
3818 static int componentorder[4] = {0, 1, 2, 3};
3820 rtexture_t *R_LoadCubemap(const char *basename)
3822 int i, j, cubemapsize;
3823 unsigned char *cubemappixels, *image_buffer;
3824 rtexture_t *cubemaptexture;
3826 // must start 0 so the first loadimagepixels has no requested width/height
3828 cubemappixels = NULL;
3829 cubemaptexture = NULL;
3830 // keep trying different suffix groups (posx, px, rt) until one loads
3831 for (j = 0;j < 3 && !cubemappixels;j++)
3833 // load the 6 images in the suffix group
3834 for (i = 0;i < 6;i++)
3836 // generate an image name based on the base and and suffix
3837 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3839 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3841 // an image loaded, make sure width and height are equal
3842 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3844 // if this is the first image to load successfully, allocate the cubemap memory
3845 if (!cubemappixels && image_width >= 1)
3847 cubemapsize = image_width;
3848 // note this clears to black, so unavailable sides are black
3849 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3851 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3853 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);
3856 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3858 Mem_Free(image_buffer);
3862 // if a cubemap loaded, upload it
3865 if (developer_loading.integer)
3866 Con_Printf("loading cubemap \"%s\"\n", basename);
3868 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);
3869 Mem_Free(cubemappixels);
3873 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3874 if (developer_loading.integer)
3876 Con_Printf("(tried tried images ");
3877 for (j = 0;j < 3;j++)
3878 for (i = 0;i < 6;i++)
3879 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3880 Con_Print(" and was unable to find any of them).\n");
3883 return cubemaptexture;
3886 rtexture_t *R_GetCubemap(const char *basename)
3889 for (i = 0;i < r_texture_numcubemaps;i++)
3890 if (r_texture_cubemaps[i] != NULL)
3891 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3892 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3893 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3894 return r_texture_whitecube;
3895 r_texture_numcubemaps++;
3896 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3897 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3898 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3899 return r_texture_cubemaps[i]->texture;
3902 void R_FreeCubemap(const char *basename)
3906 for (i = 0;i < r_texture_numcubemaps;i++)
3908 if (r_texture_cubemaps[i] != NULL)
3910 if (r_texture_cubemaps[i]->texture)
3912 if (developer_loading.integer)
3913 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3914 R_FreeTexture(r_texture_cubemaps[i]->texture);
3915 Mem_Free(r_texture_cubemaps[i]);
3916 r_texture_cubemaps[i] = NULL;
3922 void R_FreeCubemaps(void)
3925 for (i = 0;i < r_texture_numcubemaps;i++)
3927 if (developer_loading.integer)
3928 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3929 if (r_texture_cubemaps[i] != NULL)
3931 if (r_texture_cubemaps[i]->texture)
3932 R_FreeTexture(r_texture_cubemaps[i]->texture);
3933 Mem_Free(r_texture_cubemaps[i]);
3936 r_texture_numcubemaps = 0;
3939 void R_Main_FreeViewCache(void)
3941 if (r_refdef.viewcache.entityvisible)
3942 Mem_Free(r_refdef.viewcache.entityvisible);
3943 if (r_refdef.viewcache.world_pvsbits)
3944 Mem_Free(r_refdef.viewcache.world_pvsbits);
3945 if (r_refdef.viewcache.world_leafvisible)
3946 Mem_Free(r_refdef.viewcache.world_leafvisible);
3947 if (r_refdef.viewcache.world_surfacevisible)
3948 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3949 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3952 void R_Main_ResizeViewCache(void)
3954 int numentities = r_refdef.scene.numentities;
3955 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3956 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3957 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3958 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3959 if (r_refdef.viewcache.maxentities < numentities)
3961 r_refdef.viewcache.maxentities = numentities;
3962 if (r_refdef.viewcache.entityvisible)
3963 Mem_Free(r_refdef.viewcache.entityvisible);
3964 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3966 if (r_refdef.viewcache.world_numclusters != numclusters)
3968 r_refdef.viewcache.world_numclusters = numclusters;
3969 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3970 if (r_refdef.viewcache.world_pvsbits)
3971 Mem_Free(r_refdef.viewcache.world_pvsbits);
3972 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3974 if (r_refdef.viewcache.world_numleafs != numleafs)
3976 r_refdef.viewcache.world_numleafs = numleafs;
3977 if (r_refdef.viewcache.world_leafvisible)
3978 Mem_Free(r_refdef.viewcache.world_leafvisible);
3979 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3981 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3983 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3984 if (r_refdef.viewcache.world_surfacevisible)
3985 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3986 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3990 extern rtexture_t *loadingscreentexture;
3991 void gl_main_start(void)
3993 loadingscreentexture = NULL;
3994 r_texture_blanknormalmap = NULL;
3995 r_texture_white = NULL;
3996 r_texture_grey128 = NULL;
3997 r_texture_black = NULL;
3998 r_texture_whitecube = NULL;
3999 r_texture_normalizationcube = NULL;
4000 r_texture_fogattenuation = NULL;
4001 r_texture_fogheighttexture = NULL;
4002 r_texture_gammaramps = NULL;
4003 r_texture_numcubemaps = 0;
4005 r_loaddds = r_texture_dds_load.integer != 0;
4006 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4008 switch(vid.renderpath)
4010 case RENDERPATH_GL20:
4011 case RENDERPATH_D3D9:
4012 case RENDERPATH_D3D10:
4013 case RENDERPATH_D3D11:
4014 case RENDERPATH_SOFT:
4015 case RENDERPATH_GLES2:
4016 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4017 Cvar_SetValueQuick(&gl_combine, 1);
4018 Cvar_SetValueQuick(&r_glsl, 1);
4019 r_loadnormalmap = true;
4023 case RENDERPATH_GL13:
4024 case RENDERPATH_GLES1:
4025 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4026 Cvar_SetValueQuick(&gl_combine, 1);
4027 Cvar_SetValueQuick(&r_glsl, 0);
4028 r_loadnormalmap = false;
4029 r_loadgloss = false;
4032 case RENDERPATH_GL11:
4033 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4034 Cvar_SetValueQuick(&gl_combine, 0);
4035 Cvar_SetValueQuick(&r_glsl, 0);
4036 r_loadnormalmap = false;
4037 r_loadgloss = false;
4043 R_FrameData_Reset();
4047 memset(r_queries, 0, sizeof(r_queries));
4049 r_qwskincache = NULL;
4050 r_qwskincache_size = 0;
4052 // due to caching of texture_t references, the collision cache must be reset
4053 Collision_Cache_Reset(true);
4055 // set up r_skinframe loading system for textures
4056 memset(&r_skinframe, 0, sizeof(r_skinframe));
4057 r_skinframe.loadsequence = 1;
4058 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4060 r_main_texturepool = R_AllocTexturePool();
4061 R_BuildBlankTextures();
4063 if (vid.support.arb_texture_cube_map)
4066 R_BuildNormalizationCube();
4068 r_texture_fogattenuation = NULL;
4069 r_texture_fogheighttexture = NULL;
4070 r_texture_gammaramps = NULL;
4071 //r_texture_fogintensity = NULL;
4072 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4073 memset(&r_waterstate, 0, sizeof(r_waterstate));
4074 r_glsl_permutation = NULL;
4075 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4076 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4077 glslshaderstring = NULL;
4079 r_hlsl_permutation = NULL;
4080 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4081 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4083 hlslshaderstring = NULL;
4084 memset(&r_svbsp, 0, sizeof (r_svbsp));
4086 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4087 r_texture_numcubemaps = 0;
4089 r_refdef.fogmasktable_density = 0;
4092 void gl_main_shutdown(void)
4095 R_FrameData_Reset();
4097 R_Main_FreeViewCache();
4099 switch(vid.renderpath)
4101 case RENDERPATH_GL11:
4102 case RENDERPATH_GL13:
4103 case RENDERPATH_GL20:
4104 case RENDERPATH_GLES1:
4105 case RENDERPATH_GLES2:
4106 #ifdef GL_SAMPLES_PASSED_ARB
4108 qglDeleteQueriesARB(r_maxqueries, r_queries);
4111 case RENDERPATH_D3D9:
4112 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4114 case RENDERPATH_D3D10:
4115 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4117 case RENDERPATH_D3D11:
4118 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4120 case RENDERPATH_SOFT:
4126 memset(r_queries, 0, sizeof(r_queries));
4128 r_qwskincache = NULL;
4129 r_qwskincache_size = 0;
4131 // clear out the r_skinframe state
4132 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4133 memset(&r_skinframe, 0, sizeof(r_skinframe));
4136 Mem_Free(r_svbsp.nodes);
4137 memset(&r_svbsp, 0, sizeof (r_svbsp));
4138 R_FreeTexturePool(&r_main_texturepool);
4139 loadingscreentexture = NULL;
4140 r_texture_blanknormalmap = NULL;
4141 r_texture_white = NULL;
4142 r_texture_grey128 = NULL;
4143 r_texture_black = NULL;
4144 r_texture_whitecube = NULL;
4145 r_texture_normalizationcube = NULL;
4146 r_texture_fogattenuation = NULL;
4147 r_texture_fogheighttexture = NULL;
4148 r_texture_gammaramps = NULL;
4149 r_texture_numcubemaps = 0;
4150 //r_texture_fogintensity = NULL;
4151 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4152 memset(&r_waterstate, 0, sizeof(r_waterstate));
4155 r_glsl_permutation = NULL;
4156 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4157 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4158 glslshaderstring = NULL;
4160 r_hlsl_permutation = NULL;
4161 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4162 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4164 hlslshaderstring = NULL;
4167 extern void CL_ParseEntityLump(char *entitystring);
4168 void gl_main_newmap(void)
4170 // FIXME: move this code to client
4171 char *entities, entname[MAX_QPATH];
4173 Mem_Free(r_qwskincache);
4174 r_qwskincache = NULL;
4175 r_qwskincache_size = 0;
4178 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4179 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4181 CL_ParseEntityLump(entities);
4185 if (cl.worldmodel->brush.entities)
4186 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4188 R_Main_FreeViewCache();
4190 R_FrameData_Reset();
4193 void GL_Main_Init(void)
4195 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4197 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4198 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4199 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4200 if (gamemode == GAME_NEHAHRA)
4202 Cvar_RegisterVariable (&gl_fogenable);
4203 Cvar_RegisterVariable (&gl_fogdensity);
4204 Cvar_RegisterVariable (&gl_fogred);
4205 Cvar_RegisterVariable (&gl_foggreen);
4206 Cvar_RegisterVariable (&gl_fogblue);
4207 Cvar_RegisterVariable (&gl_fogstart);
4208 Cvar_RegisterVariable (&gl_fogend);
4209 Cvar_RegisterVariable (&gl_skyclip);
4211 Cvar_RegisterVariable(&r_motionblur);
4212 Cvar_RegisterVariable(&r_damageblur);
4213 Cvar_RegisterVariable(&r_motionblur_averaging);
4214 Cvar_RegisterVariable(&r_motionblur_randomize);
4215 Cvar_RegisterVariable(&r_motionblur_minblur);
4216 Cvar_RegisterVariable(&r_motionblur_maxblur);
4217 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4218 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4219 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4220 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4221 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4222 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4223 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4224 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4225 Cvar_RegisterVariable(&r_equalize_entities_by);
4226 Cvar_RegisterVariable(&r_equalize_entities_to);
4227 Cvar_RegisterVariable(&r_depthfirst);
4228 Cvar_RegisterVariable(&r_useinfinitefarclip);
4229 Cvar_RegisterVariable(&r_farclip_base);
4230 Cvar_RegisterVariable(&r_farclip_world);
4231 Cvar_RegisterVariable(&r_nearclip);
4232 Cvar_RegisterVariable(&r_deformvertexes);
4233 Cvar_RegisterVariable(&r_transparent);
4234 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4235 Cvar_RegisterVariable(&r_showoverdraw);
4236 Cvar_RegisterVariable(&r_showbboxes);
4237 Cvar_RegisterVariable(&r_showsurfaces);
4238 Cvar_RegisterVariable(&r_showtris);
4239 Cvar_RegisterVariable(&r_shownormals);
4240 Cvar_RegisterVariable(&r_showlighting);
4241 Cvar_RegisterVariable(&r_showshadowvolumes);
4242 Cvar_RegisterVariable(&r_showcollisionbrushes);
4243 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4244 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4245 Cvar_RegisterVariable(&r_showdisabledepthtest);
4246 Cvar_RegisterVariable(&r_drawportals);
4247 Cvar_RegisterVariable(&r_drawentities);
4248 Cvar_RegisterVariable(&r_draw2d);
4249 Cvar_RegisterVariable(&r_drawworld);
4250 Cvar_RegisterVariable(&r_cullentities_trace);
4251 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4252 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4253 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4254 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4255 Cvar_RegisterVariable(&r_sortentities);
4256 Cvar_RegisterVariable(&r_drawviewmodel);
4257 Cvar_RegisterVariable(&r_drawexteriormodel);
4258 Cvar_RegisterVariable(&r_speeds);
4259 Cvar_RegisterVariable(&r_fullbrights);
4260 Cvar_RegisterVariable(&r_wateralpha);
4261 Cvar_RegisterVariable(&r_dynamic);
4262 Cvar_RegisterVariable(&r_fakelight);
4263 Cvar_RegisterVariable(&r_fakelight_intensity);
4264 Cvar_RegisterVariable(&r_fullbright);
4265 Cvar_RegisterVariable(&r_shadows);
4266 Cvar_RegisterVariable(&r_shadows_darken);
4267 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4268 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4269 Cvar_RegisterVariable(&r_shadows_throwdistance);
4270 Cvar_RegisterVariable(&r_shadows_throwdirection);
4271 Cvar_RegisterVariable(&r_shadows_focus);
4272 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4273 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4274 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4275 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4276 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4277 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4278 Cvar_RegisterVariable(&r_fog_exp2);
4279 Cvar_RegisterVariable(&r_fog_clear);
4280 Cvar_RegisterVariable(&r_drawfog);
4281 Cvar_RegisterVariable(&r_transparentdepthmasking);
4282 Cvar_RegisterVariable(&r_transparent_sortmindist);
4283 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4284 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4285 Cvar_RegisterVariable(&r_texture_dds_load);
4286 Cvar_RegisterVariable(&r_texture_dds_save);
4287 Cvar_RegisterVariable(&r_textureunits);
4288 Cvar_RegisterVariable(&gl_combine);
4289 Cvar_RegisterVariable(&r_viewfbo);
4290 Cvar_RegisterVariable(&r_viewscale);
4291 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4292 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4293 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4294 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4295 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4296 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4297 Cvar_RegisterVariable(&r_glsl);
4298 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4299 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4300 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4301 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4302 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4303 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4304 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4305 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4306 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4307 Cvar_RegisterVariable(&r_glsl_postprocess);
4308 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4309 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4310 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4311 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4312 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4313 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4314 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4315 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4317 Cvar_RegisterVariable(&r_water);
4318 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4319 Cvar_RegisterVariable(&r_water_clippingplanebias);
4320 Cvar_RegisterVariable(&r_water_refractdistort);
4321 Cvar_RegisterVariable(&r_water_reflectdistort);
4322 Cvar_RegisterVariable(&r_water_scissormode);
4323 Cvar_RegisterVariable(&r_water_lowquality);
4325 Cvar_RegisterVariable(&r_lerpsprites);
4326 Cvar_RegisterVariable(&r_lerpmodels);
4327 Cvar_RegisterVariable(&r_lerplightstyles);
4328 Cvar_RegisterVariable(&r_waterscroll);
4329 Cvar_RegisterVariable(&r_bloom);
4330 Cvar_RegisterVariable(&r_bloom_colorscale);
4331 Cvar_RegisterVariable(&r_bloom_brighten);
4332 Cvar_RegisterVariable(&r_bloom_blur);
4333 Cvar_RegisterVariable(&r_bloom_resolution);
4334 Cvar_RegisterVariable(&r_bloom_colorexponent);
4335 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4336 Cvar_RegisterVariable(&r_hdr);
4337 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4338 Cvar_RegisterVariable(&r_hdr_glowintensity);
4339 Cvar_RegisterVariable(&r_hdr_range);
4340 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4341 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4342 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4343 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4344 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4345 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4346 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4347 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4348 Cvar_RegisterVariable(&developer_texturelogging);
4349 Cvar_RegisterVariable(&gl_lightmaps);
4350 Cvar_RegisterVariable(&r_test);
4351 Cvar_RegisterVariable(&r_glsl_saturation);
4352 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4353 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4354 Cvar_RegisterVariable(&r_framedatasize);
4355 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4356 Cvar_SetValue("r_fullbrights", 0);
4357 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4360 extern void R_Textures_Init(void);
4361 extern void GL_Draw_Init(void);
4362 extern void GL_Main_Init(void);
4363 extern void R_Shadow_Init(void);
4364 extern void R_Sky_Init(void);
4365 extern void GL_Surf_Init(void);
4366 extern void R_Particles_Init(void);
4367 extern void R_Explosion_Init(void);
4368 extern void gl_backend_init(void);
4369 extern void Sbar_Init(void);
4370 extern void R_LightningBeams_Init(void);
4371 extern void Mod_RenderInit(void);
4372 extern void Font_Init(void);
4374 void Render_Init(void)
4387 R_LightningBeams_Init();
4397 extern char *ENGINE_EXTENSIONS;
4400 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4401 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4402 gl_version = (const char *)qglGetString(GL_VERSION);
4403 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4407 if (!gl_platformextensions)
4408 gl_platformextensions = "";
4410 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4411 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4412 Con_Printf("GL_VERSION: %s\n", gl_version);
4413 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4414 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4416 VID_CheckExtensions();
4418 // LordHavoc: report supported extensions
4419 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4421 // clear to black (loading plaque will be seen over this)
4422 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4426 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4430 if (r_trippy.integer)
4432 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4434 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4437 p = r_refdef.view.frustum + i;
4442 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4446 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4450 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4454 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4458 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4462 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4466 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4470 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4478 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4482 if (r_trippy.integer)
4484 for (i = 0;i < numplanes;i++)
4491 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4495 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4499 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4503 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4507 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4511 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4515 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4519 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527 //==================================================================================
4529 // LordHavoc: this stores temporary data used within the same frame
4531 typedef struct r_framedata_mem_s
4533 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4534 size_t size; // how much usable space
4535 size_t current; // how much space in use
4536 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4537 size_t wantedsize; // how much space was allocated
4538 unsigned char *data; // start of real data (16byte aligned)
4542 static r_framedata_mem_t *r_framedata_mem;
4544 void R_FrameData_Reset(void)
4546 while (r_framedata_mem)
4548 r_framedata_mem_t *next = r_framedata_mem->purge;
4549 Mem_Free(r_framedata_mem);
4550 r_framedata_mem = next;
4554 void R_FrameData_Resize(void)
4557 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4558 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4559 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4561 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4562 newmem->wantedsize = wantedsize;
4563 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4564 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4565 newmem->current = 0;
4567 newmem->purge = r_framedata_mem;
4568 r_framedata_mem = newmem;
4572 void R_FrameData_NewFrame(void)
4574 R_FrameData_Resize();
4575 if (!r_framedata_mem)
4577 // if we ran out of space on the last frame, free the old memory now
4578 while (r_framedata_mem->purge)
4580 // repeatedly remove the second item in the list, leaving only head
4581 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4582 Mem_Free(r_framedata_mem->purge);
4583 r_framedata_mem->purge = next;
4585 // reset the current mem pointer
4586 r_framedata_mem->current = 0;
4587 r_framedata_mem->mark = 0;
4590 void *R_FrameData_Alloc(size_t size)
4594 // align to 16 byte boundary - the data pointer is already aligned, so we
4595 // only need to ensure the size of every allocation is also aligned
4596 size = (size + 15) & ~15;
4598 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4600 // emergency - we ran out of space, allocate more memory
4601 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4602 R_FrameData_Resize();
4605 data = r_framedata_mem->data + r_framedata_mem->current;
4606 r_framedata_mem->current += size;
4608 // count the usage for stats
4609 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4610 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4612 return (void *)data;
4615 void *R_FrameData_Store(size_t size, void *data)
4617 void *d = R_FrameData_Alloc(size);
4619 memcpy(d, data, size);
4623 void R_FrameData_SetMark(void)
4625 if (!r_framedata_mem)
4627 r_framedata_mem->mark = r_framedata_mem->current;
4630 void R_FrameData_ReturnToMark(void)
4632 if (!r_framedata_mem)
4634 r_framedata_mem->current = r_framedata_mem->mark;
4637 //==================================================================================
4639 // LordHavoc: animcache originally written by Echon, rewritten since then
4642 * Animation cache prevents re-generating mesh data for an animated model
4643 * multiple times in one frame for lighting, shadowing, reflections, etc.
4646 void R_AnimCache_Free(void)
4650 void R_AnimCache_ClearCache(void)
4653 entity_render_t *ent;
4655 for (i = 0;i < r_refdef.scene.numentities;i++)
4657 ent = r_refdef.scene.entities[i];
4658 ent->animcache_vertex3f = NULL;
4659 ent->animcache_normal3f = NULL;
4660 ent->animcache_svector3f = NULL;
4661 ent->animcache_tvector3f = NULL;
4662 ent->animcache_vertexmesh = NULL;
4663 ent->animcache_vertex3fbuffer = NULL;
4664 ent->animcache_vertexmeshbuffer = NULL;
4668 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4672 // check if we need the meshbuffers
4673 if (!vid.useinterleavedarrays)
4676 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4677 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4678 // TODO: upload vertex3f buffer?
4679 if (ent->animcache_vertexmesh)
4681 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4682 for (i = 0;i < numvertices;i++)
4683 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4684 if (ent->animcache_svector3f)
4685 for (i = 0;i < numvertices;i++)
4686 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4687 if (ent->animcache_tvector3f)
4688 for (i = 0;i < numvertices;i++)
4689 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4690 if (ent->animcache_normal3f)
4691 for (i = 0;i < numvertices;i++)
4692 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4693 // TODO: upload vertexmeshbuffer?
4697 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4699 dp_model_t *model = ent->model;
4701 // see if it's already cached this frame
4702 if (ent->animcache_vertex3f)
4704 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4705 if (wantnormals || wanttangents)
4707 if (ent->animcache_normal3f)
4708 wantnormals = false;
4709 if (ent->animcache_svector3f)
4710 wanttangents = false;
4711 if (wantnormals || wanttangents)
4713 numvertices = model->surfmesh.num_vertices;
4715 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4718 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4721 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4722 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4728 // see if this ent is worth caching
4729 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4731 // get some memory for this entity and generate mesh data
4732 numvertices = model->surfmesh.num_vertices;
4733 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4735 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4738 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4739 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4741 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4742 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4747 void R_AnimCache_CacheVisibleEntities(void)
4750 qboolean wantnormals = true;
4751 qboolean wanttangents = !r_showsurfaces.integer;
4753 switch(vid.renderpath)
4755 case RENDERPATH_GL20:
4756 case RENDERPATH_D3D9:
4757 case RENDERPATH_D3D10:
4758 case RENDERPATH_D3D11:
4759 case RENDERPATH_GLES2:
4761 case RENDERPATH_GL11:
4762 case RENDERPATH_GL13:
4763 case RENDERPATH_GLES1:
4764 wanttangents = false;
4766 case RENDERPATH_SOFT:
4770 if (r_shownormals.integer)
4771 wanttangents = wantnormals = true;
4773 // TODO: thread this
4774 // NOTE: R_PrepareRTLights() also caches entities
4776 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 if (r_refdef.viewcache.entityvisible[i])
4778 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4781 //==================================================================================
4783 extern cvar_t r_overheadsprites_pushback;
4785 static void R_View_UpdateEntityLighting (void)
4788 entity_render_t *ent;
4789 vec3_t tempdiffusenormal, avg;
4790 vec_t f, fa, fd, fdd;
4791 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4793 for (i = 0;i < r_refdef.scene.numentities;i++)
4795 ent = r_refdef.scene.entities[i];
4797 // skip unseen models
4798 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4802 if (ent->model && ent->model->brush.num_leafs)
4804 // TODO: use modellight for r_ambient settings on world?
4805 VectorSet(ent->modellight_ambient, 0, 0, 0);
4806 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4807 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4811 // fetch the lighting from the worldmodel data
4812 VectorClear(ent->modellight_ambient);
4813 VectorClear(ent->modellight_diffuse);
4814 VectorClear(tempdiffusenormal);
4815 if (ent->flags & RENDER_LIGHT)
4818 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4820 // complete lightning for lit sprites
4821 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4822 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4824 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4825 org[2] = org[2] + r_overheadsprites_pushback.value;
4826 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4829 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4831 if(ent->flags & RENDER_EQUALIZE)
4833 // first fix up ambient lighting...
4834 if(r_equalize_entities_minambient.value > 0)
4836 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4839 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4840 if(fa < r_equalize_entities_minambient.value * fd)
4843 // fa'/fd' = minambient
4844 // fa'+0.25*fd' = fa+0.25*fd
4846 // fa' = fd' * minambient
4847 // fd'*(0.25+minambient) = fa+0.25*fd
4849 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4850 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4852 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4853 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
4854 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4855 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4860 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4862 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4863 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4867 // adjust brightness and saturation to target
4868 avg[0] = avg[1] = avg[2] = fa / f;
4869 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4870 avg[0] = avg[1] = avg[2] = fd / f;
4871 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4877 VectorSet(ent->modellight_ambient, 1, 1, 1);
4879 // move the light direction into modelspace coordinates for lighting code
4880 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4881 if(VectorLength2(ent->modellight_lightdir) == 0)
4882 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4883 VectorNormalize(ent->modellight_lightdir);
4887 #define MAX_LINEOFSIGHTTRACES 64
4889 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4892 vec3_t boxmins, boxmaxs;
4895 dp_model_t *model = r_refdef.scene.worldmodel;
4897 if (!model || !model->brush.TraceLineOfSight)
4900 // expand the box a little
4901 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4902 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4903 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4904 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4905 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4906 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4908 // return true if eye is inside enlarged box
4909 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4913 VectorCopy(eye, start);
4914 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4915 if (model->brush.TraceLineOfSight(model, start, end))
4918 // try various random positions
4919 for (i = 0;i < numsamples;i++)
4921 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4922 if (model->brush.TraceLineOfSight(model, start, end))
4930 static void R_View_UpdateEntityVisible (void)
4935 entity_render_t *ent;
4937 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4938 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4939 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4940 : RENDER_EXTERIORMODEL;
4941 if (!r_drawviewmodel.integer)
4942 renderimask |= RENDER_VIEWMODEL;
4943 if (!r_drawexteriormodel.integer)
4944 renderimask |= RENDER_EXTERIORMODEL;
4945 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4947 // worldmodel can check visibility
4948 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4949 for (i = 0;i < r_refdef.scene.numentities;i++)
4951 ent = r_refdef.scene.entities[i];
4952 if (!(ent->flags & renderimask))
4953 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)))
4954 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))
4955 r_refdef.viewcache.entityvisible[i] = true;
4960 // no worldmodel or it can't check visibility
4961 for (i = 0;i < r_refdef.scene.numentities;i++)
4963 ent = r_refdef.scene.entities[i];
4964 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));
4967 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4968 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4970 for (i = 0;i < r_refdef.scene.numentities;i++)
4972 if (!r_refdef.viewcache.entityvisible[i])
4974 ent = r_refdef.scene.entities[i];
4975 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4977 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4979 continue; // temp entities do pvs only
4980 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4981 ent->last_trace_visibility = realtime;
4982 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4983 r_refdef.viewcache.entityvisible[i] = 0;
4989 /// only used if skyrendermasked, and normally returns false
4990 int R_DrawBrushModelsSky (void)
4993 entity_render_t *ent;
4996 for (i = 0;i < r_refdef.scene.numentities;i++)
4998 if (!r_refdef.viewcache.entityvisible[i])
5000 ent = r_refdef.scene.entities[i];
5001 if (!ent->model || !ent->model->DrawSky)
5003 ent->model->DrawSky(ent);
5009 static void R_DrawNoModel(entity_render_t *ent);
5010 static void R_DrawModels(void)
5013 entity_render_t *ent;
5015 for (i = 0;i < r_refdef.scene.numentities;i++)
5017 if (!r_refdef.viewcache.entityvisible[i])
5019 ent = r_refdef.scene.entities[i];
5020 r_refdef.stats.entities++;
5022 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5025 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5026 Con_Printf("R_DrawModels\n");
5027 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]);
5028 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);
5029 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);
5032 if (ent->model && ent->model->Draw != NULL)
5033 ent->model->Draw(ent);
5039 static void R_DrawModelsDepth(void)
5042 entity_render_t *ent;
5044 for (i = 0;i < r_refdef.scene.numentities;i++)
5046 if (!r_refdef.viewcache.entityvisible[i])
5048 ent = r_refdef.scene.entities[i];
5049 if (ent->model && ent->model->DrawDepth != NULL)
5050 ent->model->DrawDepth(ent);
5054 static void R_DrawModelsDebug(void)
5057 entity_render_t *ent;
5059 for (i = 0;i < r_refdef.scene.numentities;i++)
5061 if (!r_refdef.viewcache.entityvisible[i])
5063 ent = r_refdef.scene.entities[i];
5064 if (ent->model && ent->model->DrawDebug != NULL)
5065 ent->model->DrawDebug(ent);
5069 static void R_DrawModelsAddWaterPlanes(void)
5072 entity_render_t *ent;
5074 for (i = 0;i < r_refdef.scene.numentities;i++)
5076 if (!r_refdef.viewcache.entityvisible[i])
5078 ent = r_refdef.scene.entities[i];
5079 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5080 ent->model->DrawAddWaterPlanes(ent);
5084 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5086 if (r_hdr_irisadaptation.integer)
5090 vec3_t diffusenormal;
5094 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5095 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5096 brightness = max(0.0000001f, brightness);
5097 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5098 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5099 current = r_hdr_irisadaptation_value.value;
5101 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5102 else if (current > goal)
5103 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5104 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5105 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5107 else if (r_hdr_irisadaptation_value.value != 1.0f)
5108 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5111 static void R_View_SetFrustum(const int *scissor)
5114 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5115 vec3_t forward, left, up, origin, v;
5119 // flipped x coordinates (because x points left here)
5120 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5121 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5123 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5124 switch(vid.renderpath)
5126 case RENDERPATH_D3D9:
5127 case RENDERPATH_D3D10:
5128 case RENDERPATH_D3D11:
5129 // non-flipped y coordinates
5130 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5131 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5133 case RENDERPATH_SOFT:
5134 case RENDERPATH_GL11:
5135 case RENDERPATH_GL13:
5136 case RENDERPATH_GL20:
5137 case RENDERPATH_GLES1:
5138 case RENDERPATH_GLES2:
5139 // non-flipped y coordinates
5140 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5141 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5146 // we can't trust r_refdef.view.forward and friends in reflected scenes
5147 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5150 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5151 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5152 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5153 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5154 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5155 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5156 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5157 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5158 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5159 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5160 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5161 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5165 zNear = r_refdef.nearclip;
5166 nudge = 1.0 - 1.0 / (1<<23);
5167 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5168 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5169 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5170 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5171 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5172 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5173 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5174 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5180 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5181 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5182 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5183 r_refdef.view.frustum[0].dist = m[15] - m[12];
5185 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5186 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5187 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5188 r_refdef.view.frustum[1].dist = m[15] + m[12];
5190 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5191 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5192 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5193 r_refdef.view.frustum[2].dist = m[15] - m[13];
5195 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5196 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5197 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5198 r_refdef.view.frustum[3].dist = m[15] + m[13];
5200 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5201 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5202 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5203 r_refdef.view.frustum[4].dist = m[15] - m[14];
5205 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5206 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5207 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5208 r_refdef.view.frustum[5].dist = m[15] + m[14];
5211 if (r_refdef.view.useperspective)
5213 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5214 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]);
5215 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]);
5216 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]);
5217 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]);
5219 // then the normals from the corners relative to origin
5220 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5221 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5222 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5223 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5225 // in a NORMAL view, forward cross left == up
5226 // in a REFLECTED view, forward cross left == down
5227 // so our cross products above need to be adjusted for a left handed coordinate system
5228 CrossProduct(forward, left, v);
5229 if(DotProduct(v, up) < 0)
5231 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5232 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5233 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5234 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5237 // Leaving those out was a mistake, those were in the old code, and they
5238 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5239 // I couldn't reproduce it after adding those normalizations. --blub
5240 VectorNormalize(r_refdef.view.frustum[0].normal);
5241 VectorNormalize(r_refdef.view.frustum[1].normal);
5242 VectorNormalize(r_refdef.view.frustum[2].normal);
5243 VectorNormalize(r_refdef.view.frustum[3].normal);
5245 // make the corners absolute
5246 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5247 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5248 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5249 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5252 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5254 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5255 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5256 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5257 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5258 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5262 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5263 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5264 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5265 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5266 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5267 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5268 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5269 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5270 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5271 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5273 r_refdef.view.numfrustumplanes = 5;
5275 if (r_refdef.view.useclipplane)
5277 r_refdef.view.numfrustumplanes = 6;
5278 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5281 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5282 PlaneClassify(r_refdef.view.frustum + i);
5284 // LordHavoc: note to all quake engine coders, Quake had a special case
5285 // for 90 degrees which assumed a square view (wrong), so I removed it,
5286 // Quake2 has it disabled as well.
5288 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5289 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5290 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5291 //PlaneClassify(&frustum[0]);
5293 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5294 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5295 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5296 //PlaneClassify(&frustum[1]);
5298 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5299 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5300 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5301 //PlaneClassify(&frustum[2]);
5303 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5304 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5305 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5306 //PlaneClassify(&frustum[3]);
5309 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5310 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5311 //PlaneClassify(&frustum[4]);
5314 void R_View_UpdateWithScissor(const int *myscissor)
5316 R_Main_ResizeViewCache();
5317 R_View_SetFrustum(myscissor);
5318 R_View_WorldVisibility(r_refdef.view.useclipplane);
5319 R_View_UpdateEntityVisible();
5320 R_View_UpdateEntityLighting();
5323 void R_View_Update(void)
5325 R_Main_ResizeViewCache();
5326 R_View_SetFrustum(NULL);
5327 R_View_WorldVisibility(r_refdef.view.useclipplane);
5328 R_View_UpdateEntityVisible();
5329 R_View_UpdateEntityLighting();
5332 float viewscalefpsadjusted = 1.0f;
5334 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5336 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5337 scale = bound(0.03125f, scale, 1.0f);
5338 *outwidth = (int)ceil(width * scale);
5339 *outheight = (int)ceil(height * scale);
5342 void R_Mesh_SetMainRenderTargets(void)
5344 if (r_bloomstate.fbo_framebuffer)
5345 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5347 R_Mesh_ResetRenderTargets();
5350 void R_SetupView(qboolean allowwaterclippingplane)
5352 const float *customclipplane = NULL;
5354 int scaledwidth, scaledheight;
5355 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5357 // LordHavoc: couldn't figure out how to make this approach the
5358 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5359 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5360 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5361 dist = r_refdef.view.clipplane.dist;
5362 plane[0] = r_refdef.view.clipplane.normal[0];
5363 plane[1] = r_refdef.view.clipplane.normal[1];
5364 plane[2] = r_refdef.view.clipplane.normal[2];
5366 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5369 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5370 if (!r_refdef.view.useperspective)
5371 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);
5372 else if (vid.stencil && r_useinfinitefarclip.integer)
5373 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);
5375 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);
5376 R_Mesh_SetMainRenderTargets();
5377 R_SetViewport(&r_refdef.view.viewport);
5378 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5380 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5381 float screenplane[4];
5382 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5383 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5384 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5385 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5386 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5390 void R_EntityMatrix(const matrix4x4_t *matrix)
5392 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5394 gl_modelmatrixchanged = false;
5395 gl_modelmatrix = *matrix;
5396 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5397 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5398 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5399 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5401 switch(vid.renderpath)
5403 case RENDERPATH_D3D9:
5405 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5406 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5409 case RENDERPATH_D3D10:
5410 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5412 case RENDERPATH_D3D11:
5413 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5415 case RENDERPATH_GL11:
5416 case RENDERPATH_GL13:
5417 case RENDERPATH_GLES1:
5418 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5420 case RENDERPATH_SOFT:
5421 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5422 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5424 case RENDERPATH_GL20:
5425 case RENDERPATH_GLES2:
5426 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5427 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5433 void R_ResetViewRendering2D(void)
5435 r_viewport_t viewport;
5438 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5439 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);
5440 R_Mesh_ResetRenderTargets();
5441 R_SetViewport(&viewport);
5442 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5443 GL_Color(1, 1, 1, 1);
5444 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5445 GL_BlendFunc(GL_ONE, GL_ZERO);
5446 GL_ScissorTest(false);
5447 GL_DepthMask(false);
5448 GL_DepthRange(0, 1);
5449 GL_DepthTest(false);
5450 GL_DepthFunc(GL_LEQUAL);
5451 R_EntityMatrix(&identitymatrix);
5452 R_Mesh_ResetTextureState();
5453 GL_PolygonOffset(0, 0);
5454 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5455 switch(vid.renderpath)
5457 case RENDERPATH_GL11:
5458 case RENDERPATH_GL13:
5459 case RENDERPATH_GL20:
5460 case RENDERPATH_GLES1:
5461 case RENDERPATH_GLES2:
5462 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5464 case RENDERPATH_D3D9:
5465 case RENDERPATH_D3D10:
5466 case RENDERPATH_D3D11:
5467 case RENDERPATH_SOFT:
5470 GL_CullFace(GL_NONE);
5473 void R_ResetViewRendering3D(void)
5478 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5479 GL_Color(1, 1, 1, 1);
5480 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5481 GL_BlendFunc(GL_ONE, GL_ZERO);
5482 GL_ScissorTest(true);
5484 GL_DepthRange(0, 1);
5486 GL_DepthFunc(GL_LEQUAL);
5487 R_EntityMatrix(&identitymatrix);
5488 R_Mesh_ResetTextureState();
5489 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5490 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5491 switch(vid.renderpath)
5493 case RENDERPATH_GL11:
5494 case RENDERPATH_GL13:
5495 case RENDERPATH_GL20:
5496 case RENDERPATH_GLES1:
5497 case RENDERPATH_GLES2:
5498 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5500 case RENDERPATH_D3D9:
5501 case RENDERPATH_D3D10:
5502 case RENDERPATH_D3D11:
5503 case RENDERPATH_SOFT:
5506 GL_CullFace(r_refdef.view.cullface_back);
5511 R_RenderView_UpdateViewVectors
5514 static void R_RenderView_UpdateViewVectors(void)
5516 // break apart the view matrix into vectors for various purposes
5517 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5518 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5519 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5520 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5521 // make an inverted copy of the view matrix for tracking sprites
5522 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5525 void R_RenderScene(void);
5526 void R_RenderWaterPlanes(void);
5528 static void R_Water_StartFrame(void)
5531 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5532 r_waterstate_waterplane_t *p;
5534 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5537 switch(vid.renderpath)
5539 case RENDERPATH_GL20:
5540 case RENDERPATH_D3D9:
5541 case RENDERPATH_D3D10:
5542 case RENDERPATH_D3D11:
5543 case RENDERPATH_SOFT:
5544 case RENDERPATH_GLES2:
5546 case RENDERPATH_GL11:
5547 case RENDERPATH_GL13:
5548 case RENDERPATH_GLES1:
5552 // set waterwidth and waterheight to the water resolution that will be
5553 // used (often less than the screen resolution for faster rendering)
5554 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5556 // calculate desired texture sizes
5557 // can't use water if the card does not support the texture size
5558 if (!r_water.integer || r_showsurfaces.integer)
5559 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5560 else if (vid.support.arb_texture_non_power_of_two)
5562 texturewidth = waterwidth;
5563 textureheight = waterheight;
5564 camerawidth = waterwidth;
5565 cameraheight = waterheight;
5569 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5570 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5571 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5572 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5575 // allocate textures as needed
5576 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5578 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5579 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5581 if (p->texture_refraction)
5582 R_FreeTexture(p->texture_refraction);
5583 p->texture_refraction = NULL;
5584 if (p->texture_reflection)
5585 R_FreeTexture(p->texture_reflection);
5586 p->texture_reflection = NULL;
5587 if (p->texture_camera)
5588 R_FreeTexture(p->texture_camera);
5589 p->texture_camera = NULL;
5591 memset(&r_waterstate, 0, sizeof(r_waterstate));
5592 r_waterstate.texturewidth = texturewidth;
5593 r_waterstate.textureheight = textureheight;
5594 r_waterstate.camerawidth = camerawidth;
5595 r_waterstate.cameraheight = cameraheight;
5598 if (r_waterstate.texturewidth)
5600 int scaledwidth, scaledheight;
5602 r_waterstate.enabled = true;
5604 // when doing a reduced render (HDR) we want to use a smaller area
5605 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5606 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5607 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5609 // set up variables that will be used in shader setup
5610 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5611 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5612 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5613 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5616 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5617 r_waterstate.numwaterplanes = 0;
5620 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5622 int triangleindex, planeindex;
5628 r_waterstate_waterplane_t *p;
5629 texture_t *t = R_GetCurrentTexture(surface->texture);
5631 // just use the first triangle with a valid normal for any decisions
5632 VectorClear(normal);
5633 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5635 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5636 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5637 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5638 TriangleNormal(vert[0], vert[1], vert[2], normal);
5639 if (VectorLength2(normal) >= 0.001)
5643 VectorCopy(normal, plane.normal);
5644 VectorNormalize(plane.normal);
5645 plane.dist = DotProduct(vert[0], plane.normal);
5646 PlaneClassify(&plane);
5647 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5649 // skip backfaces (except if nocullface is set)
5650 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5652 VectorNegate(plane.normal, plane.normal);
5654 PlaneClassify(&plane);
5658 // find a matching plane if there is one
5659 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5660 if(p->camera_entity == t->camera_entity)
5661 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5663 if (planeindex >= r_waterstate.maxwaterplanes)
5664 return; // nothing we can do, out of planes
5666 // if this triangle does not fit any known plane rendered this frame, add one
5667 if (planeindex >= r_waterstate.numwaterplanes)
5669 // store the new plane
5670 r_waterstate.numwaterplanes++;
5672 // clear materialflags and pvs
5673 p->materialflags = 0;
5674 p->pvsvalid = false;
5675 p->camera_entity = t->camera_entity;
5676 VectorCopy(surface->mins, p->mins);
5677 VectorCopy(surface->maxs, p->maxs);
5682 p->mins[0] = min(p->mins[0], surface->mins[0]);
5683 p->mins[1] = min(p->mins[1], surface->mins[1]);
5684 p->mins[2] = min(p->mins[2], surface->mins[2]);
5685 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5686 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5687 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5689 // merge this surface's materialflags into the waterplane
5690 p->materialflags |= t->currentmaterialflags;
5691 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5693 // merge this surface's PVS into the waterplane
5694 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5695 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5696 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5698 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5704 extern cvar_t r_drawparticles;
5705 extern cvar_t r_drawdecals;
5707 static void R_Water_ProcessPlanes(void)
5710 r_refdef_view_t originalview;
5711 r_refdef_view_t myview;
5712 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;
5713 r_waterstate_waterplane_t *p;
5716 originalview = r_refdef.view;
5718 // lowquality hack, temporarily shut down some cvars and restore afterwards
5719 qualityreduction = r_water_lowquality.integer;
5720 if (qualityreduction > 0)
5722 if (qualityreduction >= 1)
5724 old_r_shadows = r_shadows.integer;
5725 old_r_worldrtlight = r_shadow_realtime_world.integer;
5726 old_r_dlight = r_shadow_realtime_dlight.integer;
5727 Cvar_SetValueQuick(&r_shadows, 0);
5728 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5729 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5731 if (qualityreduction >= 2)
5733 old_r_dynamic = r_dynamic.integer;
5734 old_r_particles = r_drawparticles.integer;
5735 old_r_decals = r_drawdecals.integer;
5736 Cvar_SetValueQuick(&r_dynamic, 0);
5737 Cvar_SetValueQuick(&r_drawparticles, 0);
5738 Cvar_SetValueQuick(&r_drawdecals, 0);
5742 // make sure enough textures are allocated
5743 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5745 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5747 if (!p->texture_refraction)
5748 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);
5749 if (!p->texture_refraction)
5752 else if (p->materialflags & MATERIALFLAG_CAMERA)
5754 if (!p->texture_camera)
5755 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);
5756 if (!p->texture_camera)
5760 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5762 if (!p->texture_reflection)
5763 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);
5764 if (!p->texture_reflection)
5770 r_refdef.view = originalview;
5771 r_refdef.view.showdebug = false;
5772 r_refdef.view.width = r_waterstate.waterwidth;
5773 r_refdef.view.height = r_waterstate.waterheight;
5774 r_refdef.view.useclipplane = true;
5775 myview = r_refdef.view;
5776 r_waterstate.renderingscene = true;
5777 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5779 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5781 r_refdef.view = myview;
5782 if(r_water_scissormode.integer)
5785 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5786 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5789 // render reflected scene and copy into texture
5790 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5791 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5792 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5793 r_refdef.view.clipplane = p->plane;
5794 // reverse the cullface settings for this render
5795 r_refdef.view.cullface_front = GL_FRONT;
5796 r_refdef.view.cullface_back = GL_BACK;
5797 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5799 r_refdef.view.usecustompvs = true;
5801 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5803 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5806 R_ResetViewRendering3D();
5807 R_ClearScreen(r_refdef.fogenabled);
5808 if(r_water_scissormode.integer & 2)
5809 R_View_UpdateWithScissor(myscissor);
5812 if(r_water_scissormode.integer & 1)
5813 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5816 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);
5819 // render the normal view scene and copy into texture
5820 // (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)
5821 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5823 r_refdef.view = myview;
5824 if(r_water_scissormode.integer)
5827 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5828 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5831 r_waterstate.renderingrefraction = true;
5833 r_refdef.view.clipplane = p->plane;
5834 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5835 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5837 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5839 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5840 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5841 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5842 R_RenderView_UpdateViewVectors();
5843 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5845 r_refdef.view.usecustompvs = true;
5846 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);
5850 PlaneClassify(&r_refdef.view.clipplane);
5852 R_ResetViewRendering3D();
5853 R_ClearScreen(r_refdef.fogenabled);
5854 if(r_water_scissormode.integer & 2)
5855 R_View_UpdateWithScissor(myscissor);
5858 if(r_water_scissormode.integer & 1)
5859 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5862 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);
5863 r_waterstate.renderingrefraction = false;
5865 else if (p->materialflags & MATERIALFLAG_CAMERA)
5867 r_refdef.view = myview;
5869 r_refdef.view.clipplane = p->plane;
5870 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5871 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5873 r_refdef.view.width = r_waterstate.camerawidth;
5874 r_refdef.view.height = r_waterstate.cameraheight;
5875 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5876 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5878 if(p->camera_entity)
5880 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5881 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5884 // note: all of the view is used for displaying... so
5885 // there is no use in scissoring
5887 // reverse the cullface settings for this render
5888 r_refdef.view.cullface_front = GL_FRONT;
5889 r_refdef.view.cullface_back = GL_BACK;
5890 // also reverse the view matrix
5891 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
5892 R_RenderView_UpdateViewVectors();
5893 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5895 r_refdef.view.usecustompvs = true;
5896 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);
5899 // camera needs no clipplane
5900 r_refdef.view.useclipplane = false;
5902 PlaneClassify(&r_refdef.view.clipplane);
5904 R_ResetViewRendering3D();
5905 R_ClearScreen(r_refdef.fogenabled);
5909 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);
5910 r_waterstate.renderingrefraction = false;
5914 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5915 r_waterstate.renderingscene = false;
5916 r_refdef.view = originalview;
5917 R_ResetViewRendering3D();
5918 R_ClearScreen(r_refdef.fogenabled);
5922 r_refdef.view = originalview;
5923 r_waterstate.renderingscene = false;
5924 Cvar_SetValueQuick(&r_water, 0);
5925 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5927 // lowquality hack, restore cvars
5928 if (qualityreduction > 0)
5930 if (qualityreduction >= 1)
5932 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5933 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5934 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5936 if (qualityreduction >= 2)
5938 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5939 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5940 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5945 void R_Bloom_StartFrame(void)
5947 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5948 int viewwidth, viewheight;
5951 if (r_viewscale_fpsscaling.integer)
5953 double actualframetime;
5954 double targetframetime;
5956 actualframetime = r_refdef.lastdrawscreentime;
5957 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5958 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5959 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5960 if (r_viewscale_fpsscaling_stepsize.value > 0)
5961 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5962 viewscalefpsadjusted += adjust;
5963 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5966 viewscalefpsadjusted = 1.0f;
5968 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5970 switch(vid.renderpath)
5972 case RENDERPATH_GL20:
5973 case RENDERPATH_D3D9:
5974 case RENDERPATH_D3D10:
5975 case RENDERPATH_D3D11:
5976 case RENDERPATH_SOFT:
5977 case RENDERPATH_GLES2:
5979 case RENDERPATH_GL11:
5980 case RENDERPATH_GL13:
5981 case RENDERPATH_GLES1:
5985 // set bloomwidth and bloomheight to the bloom resolution that will be
5986 // used (often less than the screen resolution for faster rendering)
5987 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5988 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5989 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5990 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5991 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5993 // calculate desired texture sizes
5994 if (vid.support.arb_texture_non_power_of_two)
5996 screentexturewidth = vid.width;
5997 screentextureheight = vid.height;
5998 bloomtexturewidth = r_bloomstate.bloomwidth;
5999 bloomtextureheight = r_bloomstate.bloomheight;
6003 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6004 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6005 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6006 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6009 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))
6011 Cvar_SetValueQuick(&r_hdr, 0);
6012 Cvar_SetValueQuick(&r_bloom, 0);
6013 Cvar_SetValueQuick(&r_motionblur, 0);
6014 Cvar_SetValueQuick(&r_damageblur, 0);
6017 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)
6018 screentexturewidth = screentextureheight = 0;
6019 if (!r_hdr.integer && !r_bloom.integer)
6020 bloomtexturewidth = bloomtextureheight = 0;
6022 textype = TEXTYPE_COLORBUFFER;
6023 switch (vid.renderpath)
6025 case RENDERPATH_GL20:
6026 case RENDERPATH_GLES2:
6027 if (vid.support.ext_framebuffer_object)
6029 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6030 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6033 case RENDERPATH_GL11:
6034 case RENDERPATH_GL13:
6035 case RENDERPATH_GLES1:
6036 case RENDERPATH_D3D9:
6037 case RENDERPATH_D3D10:
6038 case RENDERPATH_D3D11:
6039 case RENDERPATH_SOFT:
6043 // allocate textures as needed
6044 if (r_bloomstate.screentexturewidth != screentexturewidth
6045 || r_bloomstate.screentextureheight != screentextureheight
6046 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6047 || r_bloomstate.bloomtextureheight != bloomtextureheight
6048 || r_bloomstate.texturetype != textype
6049 || r_bloomstate.viewfbo != r_viewfbo.integer)
6051 if (r_bloomstate.texture_bloom)
6052 R_FreeTexture(r_bloomstate.texture_bloom);
6053 r_bloomstate.texture_bloom = NULL;
6054 if (r_bloomstate.texture_screen)
6055 R_FreeTexture(r_bloomstate.texture_screen);
6056 r_bloomstate.texture_screen = NULL;
6057 if (r_bloomstate.fbo_framebuffer)
6058 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6059 r_bloomstate.fbo_framebuffer = 0;
6060 if (r_bloomstate.texture_framebuffercolor)
6061 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6062 r_bloomstate.texture_framebuffercolor = NULL;
6063 if (r_bloomstate.texture_framebufferdepth)
6064 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6065 r_bloomstate.texture_framebufferdepth = NULL;
6066 r_bloomstate.screentexturewidth = screentexturewidth;
6067 r_bloomstate.screentextureheight = screentextureheight;
6068 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6069 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);
6070 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6072 // FIXME: choose depth bits based on a cvar
6073 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6074 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);
6075 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6076 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6078 // render depth into one texture and normalmap into the other
6082 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6083 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6084 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6085 if (status != GL_FRAMEBUFFER_COMPLETE)
6086 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6090 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6091 r_bloomstate.bloomtextureheight = bloomtextureheight;
6092 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6093 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);
6094 r_bloomstate.viewfbo = r_viewfbo.integer;
6095 r_bloomstate.texturetype = textype;
6098 // when doing a reduced render (HDR) we want to use a smaller area
6099 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6100 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6101 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6102 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6103 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6105 // set up a texcoord array for the full resolution screen image
6106 // (we have to keep this around to copy back during final render)
6107 r_bloomstate.screentexcoord2f[0] = 0;
6108 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6109 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6110 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6111 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6112 r_bloomstate.screentexcoord2f[5] = 0;
6113 r_bloomstate.screentexcoord2f[6] = 0;
6114 r_bloomstate.screentexcoord2f[7] = 0;
6116 // set up a texcoord array for the reduced resolution bloom image
6117 // (which will be additive blended over the screen image)
6118 r_bloomstate.bloomtexcoord2f[0] = 0;
6119 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6120 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6121 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6122 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6123 r_bloomstate.bloomtexcoord2f[5] = 0;
6124 r_bloomstate.bloomtexcoord2f[6] = 0;
6125 r_bloomstate.bloomtexcoord2f[7] = 0;
6127 switch(vid.renderpath)
6129 case RENDERPATH_GL11:
6130 case RENDERPATH_GL13:
6131 case RENDERPATH_GL20:
6132 case RENDERPATH_SOFT:
6133 case RENDERPATH_GLES1:
6134 case RENDERPATH_GLES2:
6136 case RENDERPATH_D3D9:
6137 case RENDERPATH_D3D10:
6138 case RENDERPATH_D3D11:
6141 for (i = 0;i < 4;i++)
6143 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6144 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6145 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6146 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6152 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6154 r_bloomstate.enabled = true;
6155 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6158 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);
6160 if (r_bloomstate.fbo_framebuffer)
6161 r_refdef.view.clear = true;
6164 void R_Bloom_CopyBloomTexture(float colorscale)
6166 r_refdef.stats.bloom++;
6168 // scale down screen texture to the bloom texture size
6170 R_Mesh_SetMainRenderTargets();
6171 R_SetViewport(&r_bloomstate.viewport);
6172 GL_BlendFunc(GL_ONE, GL_ZERO);
6173 GL_Color(colorscale, colorscale, colorscale, 1);
6174 // 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...
6175 switch(vid.renderpath)
6177 case RENDERPATH_GL11:
6178 case RENDERPATH_GL13:
6179 case RENDERPATH_GL20:
6180 case RENDERPATH_GLES1:
6181 case RENDERPATH_GLES2:
6182 case RENDERPATH_SOFT:
6183 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6185 case RENDERPATH_D3D9:
6186 case RENDERPATH_D3D10:
6187 case RENDERPATH_D3D11:
6188 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6191 // TODO: do boxfilter scale-down in shader?
6192 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6193 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6194 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6196 // we now have a bloom image in the framebuffer
6197 // copy it into the bloom image texture for later processing
6198 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);
6199 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6202 void R_Bloom_CopyHDRTexture(void)
6204 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);
6205 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6208 void R_Bloom_MakeTexture(void)
6211 float xoffset, yoffset, r, brighten;
6213 r_refdef.stats.bloom++;
6215 R_ResetViewRendering2D();
6217 // we have a bloom image in the framebuffer
6219 R_SetViewport(&r_bloomstate.viewport);
6221 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6224 r = bound(0, r_bloom_colorexponent.value / x, 1);
6225 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6227 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6228 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6229 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6230 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6232 // copy the vertically blurred bloom view to a texture
6233 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);
6234 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6237 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6238 brighten = r_bloom_brighten.value;
6239 if (r_bloomstate.hdr)
6240 brighten *= r_hdr_range.value;
6241 brighten = sqrt(brighten);
6243 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6244 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6246 for (dir = 0;dir < 2;dir++)
6248 // blend on at multiple vertical offsets to achieve a vertical blur
6249 // TODO: do offset blends using GLSL
6250 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6251 GL_BlendFunc(GL_ONE, GL_ZERO);
6252 for (x = -range;x <= range;x++)
6254 if (!dir){xoffset = 0;yoffset = x;}
6255 else {xoffset = x;yoffset = 0;}
6256 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6257 yoffset /= (float)r_bloomstate.bloomtextureheight;
6258 // compute a texcoord array with the specified x and y offset
6259 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6260 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6261 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6262 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6263 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6264 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6265 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6266 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6267 // this r value looks like a 'dot' particle, fading sharply to
6268 // black at the edges
6269 // (probably not realistic but looks good enough)
6270 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6271 //r = brighten/(range*2+1);
6272 r = brighten / (range * 2 + 1);
6274 r *= (1 - x*x/(float)(range*range));
6275 GL_Color(r, r, r, 1);
6276 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6277 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6279 GL_BlendFunc(GL_ONE, GL_ONE);
6282 // copy the vertically blurred bloom view to a texture
6283 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);
6284 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6288 void R_HDR_RenderBloomTexture(void)
6290 int oldwidth, oldheight;
6291 float oldcolorscale;
6292 qboolean oldwaterstate;
6294 oldwaterstate = r_waterstate.enabled;
6295 oldcolorscale = r_refdef.view.colorscale;
6296 oldwidth = r_refdef.view.width;
6297 oldheight = r_refdef.view.height;
6298 r_refdef.view.width = r_bloomstate.bloomwidth;
6299 r_refdef.view.height = r_bloomstate.bloomheight;
6301 if(r_hdr.integer < 2)
6302 r_waterstate.enabled = false;
6304 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6305 // TODO: add exposure compensation features
6306 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6308 r_refdef.view.showdebug = false;
6309 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6311 R_ResetViewRendering3D();
6313 R_ClearScreen(r_refdef.fogenabled);
6314 if (r_timereport_active)
6315 R_TimeReport("HDRclear");
6318 if (r_timereport_active)
6319 R_TimeReport("visibility");
6321 // only do secondary renders with HDR if r_hdr is 2 or higher
6322 r_waterstate.numwaterplanes = 0;
6323 if (r_waterstate.enabled)
6324 R_RenderWaterPlanes();
6326 r_refdef.view.showdebug = true;
6328 r_waterstate.numwaterplanes = 0;
6330 R_ResetViewRendering2D();
6332 R_Bloom_CopyHDRTexture();
6333 R_Bloom_MakeTexture();
6335 // restore the view settings
6336 r_waterstate.enabled = oldwaterstate;
6337 r_refdef.view.width = oldwidth;
6338 r_refdef.view.height = oldheight;
6339 r_refdef.view.colorscale = oldcolorscale;
6341 R_ResetViewRendering3D();
6343 R_ClearScreen(r_refdef.fogenabled);
6344 if (r_timereport_active)
6345 R_TimeReport("viewclear");
6348 static void R_BlendView(void)
6350 unsigned int permutation;
6351 float uservecs[4][4];
6353 switch (vid.renderpath)
6355 case RENDERPATH_GL20:
6356 case RENDERPATH_D3D9:
6357 case RENDERPATH_D3D10:
6358 case RENDERPATH_D3D11:
6359 case RENDERPATH_SOFT:
6360 case RENDERPATH_GLES2:
6362 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6363 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6364 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6365 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6366 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6368 if (r_bloomstate.texture_screen)
6370 // make sure the buffer is available
6371 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6373 R_ResetViewRendering2D();
6374 R_Mesh_SetMainRenderTargets();
6376 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6378 // declare variables
6379 float blur_factor, blur_mouseaccel, blur_velocity;
6380 static float blur_average;
6381 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6383 // set a goal for the factoring
6384 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6385 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6386 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6387 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6388 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6389 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6391 // from the goal, pick an averaged value between goal and last value
6392 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6393 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6395 // enforce minimum amount of blur
6396 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6398 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6400 // calculate values into a standard alpha
6401 cl.motionbluralpha = 1 - exp(-
6403 (r_motionblur.value * blur_factor / 80)
6405 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6408 max(0.0001, cl.time - cl.oldtime) // fps independent
6411 // randomization for the blur value to combat persistent ghosting
6412 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6413 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6416 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6418 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6419 GL_Color(1, 1, 1, cl.motionbluralpha);
6420 switch(vid.renderpath)
6422 case RENDERPATH_GL11:
6423 case RENDERPATH_GL13:
6424 case RENDERPATH_GL20:
6425 case RENDERPATH_GLES1:
6426 case RENDERPATH_GLES2:
6427 case RENDERPATH_SOFT:
6428 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6430 case RENDERPATH_D3D9:
6431 case RENDERPATH_D3D10:
6432 case RENDERPATH_D3D11:
6433 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6436 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6437 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6438 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6441 // updates old view angles for next pass
6442 VectorCopy(cl.viewangles, blur_oldangles);
6445 // copy view into the screen texture
6446 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);
6447 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6449 else if (!r_bloomstate.texture_bloom)
6451 // we may still have to do view tint...
6452 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6454 // apply a color tint to the whole view
6455 R_ResetViewRendering2D();
6456 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6457 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6458 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6459 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6460 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6462 break; // no screen processing, no bloom, skip it
6465 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6467 // render simple bloom effect
6468 // copy the screen and shrink it and darken it for the bloom process
6469 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6470 // make the bloom texture
6471 R_Bloom_MakeTexture();
6474 #if _MSC_VER >= 1400
6475 #define sscanf sscanf_s
6477 memset(uservecs, 0, sizeof(uservecs));
6478 if (r_glsl_postprocess_uservec1_enable.integer)
6479 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6480 if (r_glsl_postprocess_uservec2_enable.integer)
6481 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6482 if (r_glsl_postprocess_uservec3_enable.integer)
6483 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6484 if (r_glsl_postprocess_uservec4_enable.integer)
6485 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6487 R_ResetViewRendering2D();
6488 GL_Color(1, 1, 1, 1);
6489 GL_BlendFunc(GL_ONE, GL_ZERO);
6491 switch(vid.renderpath)
6493 case RENDERPATH_GL20:
6494 case RENDERPATH_GLES2:
6495 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6496 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6497 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6498 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6499 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6500 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]);
6501 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6502 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]);
6503 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]);
6504 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]);
6505 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]);
6506 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6507 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6508 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);
6510 case RENDERPATH_D3D9:
6512 // 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...
6513 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6514 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6515 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6516 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6517 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6518 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6519 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6520 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6521 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6522 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6523 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6524 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6525 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6526 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6529 case RENDERPATH_D3D10:
6530 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6532 case RENDERPATH_D3D11:
6533 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6535 case RENDERPATH_SOFT:
6536 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6537 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6538 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6539 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6540 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6541 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6542 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6543 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6544 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6545 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6546 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6547 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6548 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6549 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6554 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6555 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6557 case RENDERPATH_GL11:
6558 case RENDERPATH_GL13:
6559 case RENDERPATH_GLES1:
6560 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6562 // apply a color tint to the whole view
6563 R_ResetViewRendering2D();
6564 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6565 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6566 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6567 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6568 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6574 matrix4x4_t r_waterscrollmatrix;
6576 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6579 if (gamemode == GAME_NEHAHRA)
6581 if (gl_fogenable.integer)
6583 r_refdef.oldgl_fogenable = true;
6584 r_refdef.fog_density = gl_fogdensity.value;
6585 r_refdef.fog_red = gl_fogred.value;
6586 r_refdef.fog_green = gl_foggreen.value;
6587 r_refdef.fog_blue = gl_fogblue.value;
6588 r_refdef.fog_alpha = 1;
6589 r_refdef.fog_start = 0;
6590 r_refdef.fog_end = gl_skyclip.value;
6591 r_refdef.fog_height = 1<<30;
6592 r_refdef.fog_fadedepth = 128;
6594 else if (r_refdef.oldgl_fogenable)
6596 r_refdef.oldgl_fogenable = false;
6597 r_refdef.fog_density = 0;
6598 r_refdef.fog_red = 0;
6599 r_refdef.fog_green = 0;
6600 r_refdef.fog_blue = 0;
6601 r_refdef.fog_alpha = 0;
6602 r_refdef.fog_start = 0;
6603 r_refdef.fog_end = 0;
6604 r_refdef.fog_height = 1<<30;
6605 r_refdef.fog_fadedepth = 128;
6610 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6611 r_refdef.fog_start = max(0, r_refdef.fog_start);
6612 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6614 if (r_refdef.fog_density && r_drawfog.integer)
6616 r_refdef.fogenabled = true;
6617 // this is the point where the fog reaches 0.9986 alpha, which we
6618 // consider a good enough cutoff point for the texture
6619 // (0.9986 * 256 == 255.6)
6620 if (r_fog_exp2.integer)
6621 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6623 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6624 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6625 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6626 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6627 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6628 R_BuildFogHeightTexture();
6629 // fog color was already set
6630 // update the fog texture
6631 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)
6632 R_BuildFogTexture();
6633 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6634 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6637 r_refdef.fogenabled = false;
6640 if (r_refdef.fog_density)
6642 r_refdef.fogcolor[0] = r_refdef.fog_red;
6643 r_refdef.fogcolor[1] = r_refdef.fog_green;
6644 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6646 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6647 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6648 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6649 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6653 VectorCopy(r_refdef.fogcolor, fogvec);
6654 // color.rgb *= ContrastBoost * SceneBrightness;
6655 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6656 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6657 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6658 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6663 void R_UpdateVariables(void)
6667 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6669 r_refdef.farclip = r_farclip_base.value;
6670 if (r_refdef.scene.worldmodel)
6671 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6672 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6674 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6675 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6676 r_refdef.polygonfactor = 0;
6677 r_refdef.polygonoffset = 0;
6678 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6679 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6681 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6682 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6683 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6684 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6685 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6686 if (FAKELIGHT_ENABLED)
6688 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6690 if (r_showsurfaces.integer)
6692 r_refdef.scene.rtworld = false;
6693 r_refdef.scene.rtworldshadows = false;
6694 r_refdef.scene.rtdlight = false;
6695 r_refdef.scene.rtdlightshadows = false;
6696 r_refdef.lightmapintensity = 0;
6699 switch(vid.renderpath)
6701 case RENDERPATH_GL20:
6702 case RENDERPATH_D3D9:
6703 case RENDERPATH_D3D10:
6704 case RENDERPATH_D3D11:
6705 case RENDERPATH_SOFT:
6706 case RENDERPATH_GLES2:
6707 if(v_glslgamma.integer && !vid_gammatables_trivial)
6709 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6711 // build GLSL gamma texture
6712 #define RAMPWIDTH 256
6713 unsigned short ramp[RAMPWIDTH * 3];
6714 unsigned char rampbgr[RAMPWIDTH][4];
6717 r_texture_gammaramps_serial = vid_gammatables_serial;
6719 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6720 for(i = 0; i < RAMPWIDTH; ++i)
6722 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6723 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6724 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6727 if (r_texture_gammaramps)
6729 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6733 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6739 // remove GLSL gamma texture
6742 case RENDERPATH_GL11:
6743 case RENDERPATH_GL13:
6744 case RENDERPATH_GLES1:
6749 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6750 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6756 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6757 if( scenetype != r_currentscenetype ) {
6758 // store the old scenetype
6759 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6760 r_currentscenetype = scenetype;
6761 // move in the new scene
6762 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6771 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6773 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6774 if( scenetype == r_currentscenetype ) {
6775 return &r_refdef.scene;
6777 return &r_scenes_store[ scenetype ];
6781 int R_SortEntities_Compare(const void *ap, const void *bp)
6783 const entity_render_t *a = *(const entity_render_t **)ap;
6784 const entity_render_t *b = *(const entity_render_t **)bp;
6787 if(a->model < b->model)
6789 if(a->model > b->model)
6793 // TODO possibly calculate the REAL skinnum here first using
6795 if(a->skinnum < b->skinnum)
6797 if(a->skinnum > b->skinnum)
6800 // everything we compared is equal
6803 void R_SortEntities(void)
6805 // below or equal 2 ents, sorting never gains anything
6806 if(r_refdef.scene.numentities <= 2)
6809 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6817 int dpsoftrast_test;
6818 extern void R_Shadow_UpdateBounceGridTexture(void);
6819 extern cvar_t r_shadow_bouncegrid;
6820 void R_RenderView(void)
6822 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6824 dpsoftrast_test = r_test.integer;
6826 if (r_timereport_active)
6827 R_TimeReport("start");
6828 r_textureframe++; // used only by R_GetCurrentTexture
6829 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6831 if(R_CompileShader_CheckStaticParms())
6834 if (!r_drawentities.integer)
6835 r_refdef.scene.numentities = 0;
6836 else if (r_sortentities.integer)
6839 R_AnimCache_ClearCache();
6840 R_FrameData_NewFrame();
6842 /* adjust for stereo display */
6843 if(R_Stereo_Active())
6845 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);
6846 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6849 if (r_refdef.view.isoverlay)
6851 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6852 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6853 R_TimeReport("depthclear");
6855 r_refdef.view.showdebug = false;
6857 r_waterstate.enabled = false;
6858 r_waterstate.numwaterplanes = 0;
6862 r_refdef.view.matrix = originalmatrix;
6868 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6870 r_refdef.view.matrix = originalmatrix;
6871 return; //Host_Error ("R_RenderView: NULL worldmodel");
6874 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6876 R_RenderView_UpdateViewVectors();
6878 R_Shadow_UpdateWorldLightSelection();
6880 R_Bloom_StartFrame();
6881 R_Water_StartFrame();
6884 if (r_timereport_active)
6885 R_TimeReport("viewsetup");
6887 R_ResetViewRendering3D();
6889 if (r_refdef.view.clear || r_refdef.fogenabled)
6891 R_ClearScreen(r_refdef.fogenabled);
6892 if (r_timereport_active)
6893 R_TimeReport("viewclear");
6895 r_refdef.view.clear = true;
6897 // this produces a bloom texture to be used in R_BlendView() later
6898 if (r_bloomstate.hdr)
6900 R_HDR_RenderBloomTexture();
6901 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6902 r_textureframe++; // used only by R_GetCurrentTexture
6905 r_refdef.view.showdebug = true;
6908 if (r_timereport_active)
6909 R_TimeReport("visibility");
6911 R_Shadow_UpdateBounceGridTexture();
6912 if (r_timereport_active && r_shadow_bouncegrid.integer)
6913 R_TimeReport("bouncegrid");
6915 r_waterstate.numwaterplanes = 0;
6916 if (r_waterstate.enabled)
6917 R_RenderWaterPlanes();
6920 r_waterstate.numwaterplanes = 0;
6923 if (r_timereport_active)
6924 R_TimeReport("blendview");
6926 GL_Scissor(0, 0, vid.width, vid.height);
6927 GL_ScissorTest(false);
6929 r_refdef.view.matrix = originalmatrix;
6934 void R_RenderWaterPlanes(void)
6936 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6938 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6939 if (r_timereport_active)
6940 R_TimeReport("waterworld");
6943 // don't let sound skip if going slow
6944 if (r_refdef.scene.extraupdate)
6947 R_DrawModelsAddWaterPlanes();
6948 if (r_timereport_active)
6949 R_TimeReport("watermodels");
6951 if (r_waterstate.numwaterplanes)
6953 R_Water_ProcessPlanes();
6954 if (r_timereport_active)
6955 R_TimeReport("waterscenes");
6959 extern void R_DrawLightningBeams (void);
6960 extern void VM_CL_AddPolygonsToMeshQueue (void);
6961 extern void R_DrawPortals (void);
6962 extern cvar_t cl_locs_show;
6963 static void R_DrawLocs(void);
6964 static void R_DrawEntityBBoxes(void);
6965 static void R_DrawModelDecals(void);
6966 extern void R_DrawModelShadows(void);
6967 extern void R_DrawModelShadowMaps(void);
6968 extern cvar_t cl_decals_newsystem;
6969 extern qboolean r_shadow_usingdeferredprepass;
6970 void R_RenderScene(void)
6972 qboolean shadowmapping = false;
6974 if (r_timereport_active)
6975 R_TimeReport("beginscene");
6977 r_refdef.stats.renders++;
6981 // don't let sound skip if going slow
6982 if (r_refdef.scene.extraupdate)
6985 R_MeshQueue_BeginScene();
6989 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);
6991 if (r_timereport_active)
6992 R_TimeReport("skystartframe");
6994 if (cl.csqc_vidvars.drawworld)
6996 // don't let sound skip if going slow
6997 if (r_refdef.scene.extraupdate)
7000 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7002 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7003 if (r_timereport_active)
7004 R_TimeReport("worldsky");
7007 if (R_DrawBrushModelsSky() && r_timereport_active)
7008 R_TimeReport("bmodelsky");
7010 if (skyrendermasked && skyrenderlater)
7012 // we have to force off the water clipping plane while rendering sky
7016 if (r_timereport_active)
7017 R_TimeReport("sky");
7021 R_AnimCache_CacheVisibleEntities();
7022 if (r_timereport_active)
7023 R_TimeReport("animation");
7025 R_Shadow_PrepareLights();
7026 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7027 R_Shadow_PrepareModelShadows();
7028 if (r_timereport_active)
7029 R_TimeReport("preparelights");
7031 if (R_Shadow_ShadowMappingEnabled())
7032 shadowmapping = true;
7034 if (r_shadow_usingdeferredprepass)
7035 R_Shadow_DrawPrepass();
7037 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7039 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7040 if (r_timereport_active)
7041 R_TimeReport("worlddepth");
7043 if (r_depthfirst.integer >= 2)
7045 R_DrawModelsDepth();
7046 if (r_timereport_active)
7047 R_TimeReport("modeldepth");
7050 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7052 R_DrawModelShadowMaps();
7053 R_ResetViewRendering3D();
7054 // don't let sound skip if going slow
7055 if (r_refdef.scene.extraupdate)
7059 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7061 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7062 if (r_timereport_active)
7063 R_TimeReport("world");
7066 // don't let sound skip if going slow
7067 if (r_refdef.scene.extraupdate)
7071 if (r_timereport_active)
7072 R_TimeReport("models");
7074 // don't let sound skip if going slow
7075 if (r_refdef.scene.extraupdate)
7078 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7080 R_DrawModelShadows();
7081 R_ResetViewRendering3D();
7082 // don't let sound skip if going slow
7083 if (r_refdef.scene.extraupdate)
7087 if (!r_shadow_usingdeferredprepass)
7089 R_Shadow_DrawLights();
7090 if (r_timereport_active)
7091 R_TimeReport("rtlights");
7094 // don't let sound skip if going slow
7095 if (r_refdef.scene.extraupdate)
7098 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7100 R_DrawModelShadows();
7101 R_ResetViewRendering3D();
7102 // don't let sound skip if going slow
7103 if (r_refdef.scene.extraupdate)
7107 if (cl.csqc_vidvars.drawworld)
7109 if (cl_decals_newsystem.integer)
7111 R_DrawModelDecals();
7112 if (r_timereport_active)
7113 R_TimeReport("modeldecals");
7118 if (r_timereport_active)
7119 R_TimeReport("decals");
7123 if (r_timereport_active)
7124 R_TimeReport("particles");
7127 if (r_timereport_active)
7128 R_TimeReport("explosions");
7130 R_DrawLightningBeams();
7131 if (r_timereport_active)
7132 R_TimeReport("lightning");
7135 VM_CL_AddPolygonsToMeshQueue();
7137 if (r_refdef.view.showdebug)
7139 if (cl_locs_show.integer)
7142 if (r_timereport_active)
7143 R_TimeReport("showlocs");
7146 if (r_drawportals.integer)
7149 if (r_timereport_active)
7150 R_TimeReport("portals");
7153 if (r_showbboxes.value > 0)
7155 R_DrawEntityBBoxes();
7156 if (r_timereport_active)
7157 R_TimeReport("bboxes");
7161 if (r_transparent.integer)
7163 R_MeshQueue_RenderTransparent();
7164 if (r_timereport_active)
7165 R_TimeReport("drawtrans");
7168 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))
7170 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7171 if (r_timereport_active)
7172 R_TimeReport("worlddebug");
7173 R_DrawModelsDebug();
7174 if (r_timereport_active)
7175 R_TimeReport("modeldebug");
7178 if (cl.csqc_vidvars.drawworld)
7180 R_Shadow_DrawCoronas();
7181 if (r_timereport_active)
7182 R_TimeReport("coronas");
7187 GL_DepthTest(false);
7188 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7189 GL_Color(1, 1, 1, 1);
7190 qglBegin(GL_POLYGON);
7191 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7192 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7193 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7194 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7196 qglBegin(GL_POLYGON);
7197 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]);
7198 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]);
7199 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]);
7200 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]);
7202 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7206 // don't let sound skip if going slow
7207 if (r_refdef.scene.extraupdate)
7210 R_ResetViewRendering2D();
7213 static const unsigned short bboxelements[36] =
7223 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7226 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7228 RSurf_ActiveWorldEntity();
7230 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7231 GL_DepthMask(false);
7232 GL_DepthRange(0, 1);
7233 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7234 // R_Mesh_ResetTextureState();
7236 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7237 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7238 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7239 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7240 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7241 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7242 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7243 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7244 R_FillColors(color4f, 8, cr, cg, cb, ca);
7245 if (r_refdef.fogenabled)
7247 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7249 f1 = RSurf_FogVertex(v);
7251 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7252 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7253 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7256 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7257 R_Mesh_ResetTextureState();
7258 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7259 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7262 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7266 prvm_edict_t *edict;
7267 prvm_prog_t *prog_save = prog;
7269 // this function draws bounding boxes of server entities
7273 GL_CullFace(GL_NONE);
7274 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7278 for (i = 0;i < numsurfaces;i++)
7280 edict = PRVM_EDICT_NUM(surfacelist[i]);
7281 switch ((int)PRVM_serveredictfloat(edict, solid))
7283 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7284 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7285 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7286 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7287 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7288 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7290 color[3] *= r_showbboxes.value;
7291 color[3] = bound(0, color[3], 1);
7292 GL_DepthTest(!r_showdisabledepthtest.integer);
7293 GL_CullFace(r_refdef.view.cullface_front);
7294 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7300 static void R_DrawEntityBBoxes(void)
7303 prvm_edict_t *edict;
7305 prvm_prog_t *prog_save = prog;
7307 // this function draws bounding boxes of server entities
7313 for (i = 0;i < prog->num_edicts;i++)
7315 edict = PRVM_EDICT_NUM(i);
7316 if (edict->priv.server->free)
7318 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7319 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7321 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7323 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7324 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7330 static const int nomodelelement3i[24] =
7342 static const unsigned short nomodelelement3s[24] =
7354 static const float nomodelvertex3f[6*3] =
7364 static const float nomodelcolor4f[6*4] =
7366 0.0f, 0.0f, 0.5f, 1.0f,
7367 0.0f, 0.0f, 0.5f, 1.0f,
7368 0.0f, 0.5f, 0.0f, 1.0f,
7369 0.0f, 0.5f, 0.0f, 1.0f,
7370 0.5f, 0.0f, 0.0f, 1.0f,
7371 0.5f, 0.0f, 0.0f, 1.0f
7374 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7380 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);
7382 // this is only called once per entity so numsurfaces is always 1, and
7383 // surfacelist is always {0}, so this code does not handle batches
7385 if (rsurface.ent_flags & RENDER_ADDITIVE)
7387 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7388 GL_DepthMask(false);
7390 else if (rsurface.colormod[3] < 1)
7392 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7393 GL_DepthMask(false);
7397 GL_BlendFunc(GL_ONE, GL_ZERO);
7400 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7401 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7402 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7403 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7404 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7405 for (i = 0, c = color4f;i < 6;i++, c += 4)
7407 c[0] *= rsurface.colormod[0];
7408 c[1] *= rsurface.colormod[1];
7409 c[2] *= rsurface.colormod[2];
7410 c[3] *= rsurface.colormod[3];
7412 if (r_refdef.fogenabled)
7414 for (i = 0, c = color4f;i < 6;i++, c += 4)
7416 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7418 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7419 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7420 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7423 // R_Mesh_ResetTextureState();
7424 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7425 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7426 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7429 void R_DrawNoModel(entity_render_t *ent)
7432 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7433 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7434 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7436 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7439 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7441 vec3_t right1, right2, diff, normal;
7443 VectorSubtract (org2, org1, normal);
7445 // calculate 'right' vector for start
7446 VectorSubtract (r_refdef.view.origin, org1, diff);
7447 CrossProduct (normal, diff, right1);
7448 VectorNormalize (right1);
7450 // calculate 'right' vector for end
7451 VectorSubtract (r_refdef.view.origin, org2, diff);
7452 CrossProduct (normal, diff, right2);
7453 VectorNormalize (right2);
7455 vert[ 0] = org1[0] + width * right1[0];
7456 vert[ 1] = org1[1] + width * right1[1];
7457 vert[ 2] = org1[2] + width * right1[2];
7458 vert[ 3] = org1[0] - width * right1[0];
7459 vert[ 4] = org1[1] - width * right1[1];
7460 vert[ 5] = org1[2] - width * right1[2];
7461 vert[ 6] = org2[0] - width * right2[0];
7462 vert[ 7] = org2[1] - width * right2[1];
7463 vert[ 8] = org2[2] - width * right2[2];
7464 vert[ 9] = org2[0] + width * right2[0];
7465 vert[10] = org2[1] + width * right2[1];
7466 vert[11] = org2[2] + width * right2[2];
7469 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)
7471 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7472 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7473 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7474 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7475 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7476 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7477 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7478 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7479 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7480 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7481 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7482 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7485 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7490 VectorSet(v, x, y, z);
7491 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7492 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7494 if (i == mesh->numvertices)
7496 if (mesh->numvertices < mesh->maxvertices)
7498 VectorCopy(v, vertex3f);
7499 mesh->numvertices++;
7501 return mesh->numvertices;
7507 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7511 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7512 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7513 e = mesh->element3i + mesh->numtriangles * 3;
7514 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7516 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7517 if (mesh->numtriangles < mesh->maxtriangles)
7522 mesh->numtriangles++;
7524 element[1] = element[2];
7528 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7532 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7533 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7534 e = mesh->element3i + mesh->numtriangles * 3;
7535 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7537 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7538 if (mesh->numtriangles < mesh->maxtriangles)
7543 mesh->numtriangles++;
7545 element[1] = element[2];
7549 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7550 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7552 int planenum, planenum2;
7555 mplane_t *plane, *plane2;
7557 double temppoints[2][256*3];
7558 // figure out how large a bounding box we need to properly compute this brush
7560 for (w = 0;w < numplanes;w++)
7561 maxdist = max(maxdist, fabs(planes[w].dist));
7562 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7563 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7564 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7568 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7569 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7571 if (planenum2 == planenum)
7573 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);
7576 if (tempnumpoints < 3)
7578 // generate elements forming a triangle fan for this polygon
7579 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7583 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)
7585 texturelayer_t *layer;
7586 layer = t->currentlayers + t->currentnumlayers++;
7588 layer->depthmask = depthmask;
7589 layer->blendfunc1 = blendfunc1;
7590 layer->blendfunc2 = blendfunc2;
7591 layer->texture = texture;
7592 layer->texmatrix = *matrix;
7593 layer->color[0] = r;
7594 layer->color[1] = g;
7595 layer->color[2] = b;
7596 layer->color[3] = a;
7599 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7601 if(parms[0] == 0 && parms[1] == 0)
7603 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7604 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7609 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7612 index = parms[2] + rsurface.shadertime * parms[3];
7613 index -= floor(index);
7614 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7617 case Q3WAVEFUNC_NONE:
7618 case Q3WAVEFUNC_NOISE:
7619 case Q3WAVEFUNC_COUNT:
7622 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7623 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7624 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7625 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7626 case Q3WAVEFUNC_TRIANGLE:
7628 f = index - floor(index);
7641 f = parms[0] + parms[1] * f;
7642 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7643 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7647 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7653 matrix4x4_t matrix, temp;
7654 switch(tcmod->tcmod)
7658 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7659 matrix = r_waterscrollmatrix;
7661 matrix = identitymatrix;
7663 case Q3TCMOD_ENTITYTRANSLATE:
7664 // this is used in Q3 to allow the gamecode to control texcoord
7665 // scrolling on the entity, which is not supported in darkplaces yet.
7666 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7668 case Q3TCMOD_ROTATE:
7669 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7670 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7671 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7674 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7676 case Q3TCMOD_SCROLL:
7677 // extra care is needed because of precision breakdown with large values of time
7678 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7679 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7680 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7682 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7683 w = (int) tcmod->parms[0];
7684 h = (int) tcmod->parms[1];
7685 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7687 idx = (int) floor(f * w * h);
7688 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7690 case Q3TCMOD_STRETCH:
7691 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7692 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7694 case Q3TCMOD_TRANSFORM:
7695 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7696 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7697 VectorSet(tcmat + 6, 0 , 0 , 1);
7698 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7699 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7701 case Q3TCMOD_TURBULENT:
7702 // this is handled in the RSurf_PrepareVertices function
7703 matrix = identitymatrix;
7707 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7710 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7712 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7713 char name[MAX_QPATH];
7714 skinframe_t *skinframe;
7715 unsigned char pixels[296*194];
7716 strlcpy(cache->name, skinname, sizeof(cache->name));
7717 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7718 if (developer_loading.integer)
7719 Con_Printf("loading %s\n", name);
7720 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7721 if (!skinframe || !skinframe->base)
7724 fs_offset_t filesize;
7726 f = FS_LoadFile(name, tempmempool, true, &filesize);
7729 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7730 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7734 cache->skinframe = skinframe;
7737 texture_t *R_GetCurrentTexture(texture_t *t)
7740 const entity_render_t *ent = rsurface.entity;
7741 dp_model_t *model = ent->model;
7742 q3shaderinfo_layer_tcmod_t *tcmod;
7744 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7745 return t->currentframe;
7746 t->update_lastrenderframe = r_textureframe;
7747 t->update_lastrenderentity = (void *)ent;
7749 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7750 t->camera_entity = ent->entitynumber;
7752 t->camera_entity = 0;
7754 // switch to an alternate material if this is a q1bsp animated material
7756 texture_t *texture = t;
7757 int s = rsurface.ent_skinnum;
7758 if ((unsigned int)s >= (unsigned int)model->numskins)
7760 if (model->skinscenes)
7762 if (model->skinscenes[s].framecount > 1)
7763 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7765 s = model->skinscenes[s].firstframe;
7768 t = t + s * model->num_surfaces;
7771 // use an alternate animation if the entity's frame is not 0,
7772 // and only if the texture has an alternate animation
7773 if (rsurface.ent_alttextures && t->anim_total[1])
7774 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7776 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7778 texture->currentframe = t;
7781 // update currentskinframe to be a qw skin or animation frame
7782 if (rsurface.ent_qwskin >= 0)
7784 i = rsurface.ent_qwskin;
7785 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7787 r_qwskincache_size = cl.maxclients;
7789 Mem_Free(r_qwskincache);
7790 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7792 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7793 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7794 t->currentskinframe = r_qwskincache[i].skinframe;
7795 if (t->currentskinframe == NULL)
7796 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7798 else if (t->numskinframes >= 2)
7799 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7800 if (t->backgroundnumskinframes >= 2)
7801 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7803 t->currentmaterialflags = t->basematerialflags;
7804 t->currentalpha = rsurface.colormod[3];
7805 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7806 t->currentalpha *= r_wateralpha.value;
7807 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7808 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7809 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7810 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7811 if (!(rsurface.ent_flags & RENDER_LIGHT))
7812 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7813 else if (FAKELIGHT_ENABLED)
7815 // no modellight if using fakelight for the map
7817 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7819 // pick a model lighting mode
7820 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7821 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7823 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7825 if (rsurface.ent_flags & RENDER_ADDITIVE)
7826 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7827 else if (t->currentalpha < 1)
7828 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7829 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7830 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7831 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7832 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7833 if (t->backgroundnumskinframes)
7834 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7835 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7837 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7838 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7841 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7842 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7844 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7845 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7847 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7848 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7850 // there is no tcmod
7851 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7853 t->currenttexmatrix = r_waterscrollmatrix;
7854 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7856 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7858 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7859 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7862 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7863 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7864 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7865 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7867 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7868 if (t->currentskinframe->qpixels)
7869 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7870 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7871 if (!t->basetexture)
7872 t->basetexture = r_texture_notexture;
7873 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7874 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7875 t->nmaptexture = t->currentskinframe->nmap;
7876 if (!t->nmaptexture)
7877 t->nmaptexture = r_texture_blanknormalmap;
7878 t->glosstexture = r_texture_black;
7879 t->glowtexture = t->currentskinframe->glow;
7880 t->fogtexture = t->currentskinframe->fog;
7881 t->reflectmasktexture = t->currentskinframe->reflect;
7882 if (t->backgroundnumskinframes)
7884 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7885 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7886 t->backgroundglosstexture = r_texture_black;
7887 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7888 if (!t->backgroundnmaptexture)
7889 t->backgroundnmaptexture = r_texture_blanknormalmap;
7893 t->backgroundbasetexture = r_texture_white;
7894 t->backgroundnmaptexture = r_texture_blanknormalmap;
7895 t->backgroundglosstexture = r_texture_black;
7896 t->backgroundglowtexture = NULL;
7898 t->specularpower = r_shadow_glossexponent.value;
7899 // TODO: store reference values for these in the texture?
7900 t->specularscale = 0;
7901 if (r_shadow_gloss.integer > 0)
7903 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7905 if (r_shadow_glossintensity.value > 0)
7907 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7908 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7909 t->specularscale = r_shadow_glossintensity.value;
7912 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7914 t->glosstexture = r_texture_white;
7915 t->backgroundglosstexture = r_texture_white;
7916 t->specularscale = r_shadow_gloss2intensity.value;
7917 t->specularpower = r_shadow_gloss2exponent.value;
7920 t->specularscale *= t->specularscalemod;
7921 t->specularpower *= t->specularpowermod;
7922 t->rtlightambient = 0;
7924 // lightmaps mode looks bad with dlights using actual texturing, so turn
7925 // off the colormap and glossmap, but leave the normalmap on as it still
7926 // accurately represents the shading involved
7927 if (gl_lightmaps.integer)
7929 t->basetexture = r_texture_grey128;
7930 t->pantstexture = r_texture_black;
7931 t->shirttexture = r_texture_black;
7932 t->nmaptexture = r_texture_blanknormalmap;
7933 t->glosstexture = r_texture_black;
7934 t->glowtexture = NULL;
7935 t->fogtexture = NULL;
7936 t->reflectmasktexture = NULL;
7937 t->backgroundbasetexture = NULL;
7938 t->backgroundnmaptexture = r_texture_blanknormalmap;
7939 t->backgroundglosstexture = r_texture_black;
7940 t->backgroundglowtexture = NULL;
7941 t->specularscale = 0;
7942 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7945 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7946 VectorClear(t->dlightcolor);
7947 t->currentnumlayers = 0;
7948 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7950 int blendfunc1, blendfunc2;
7952 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7954 blendfunc1 = GL_SRC_ALPHA;
7955 blendfunc2 = GL_ONE;
7957 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7959 blendfunc1 = GL_SRC_ALPHA;
7960 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7962 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7964 blendfunc1 = t->customblendfunc[0];
7965 blendfunc2 = t->customblendfunc[1];
7969 blendfunc1 = GL_ONE;
7970 blendfunc2 = GL_ZERO;
7972 // don't colormod evilblend textures
7973 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7974 VectorSet(t->lightmapcolor, 1, 1, 1);
7975 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7976 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7978 // fullbright is not affected by r_refdef.lightmapintensity
7979 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]);
7980 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7981 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]);
7982 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7983 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]);
7987 vec3_t ambientcolor;
7989 // set the color tint used for lights affecting this surface
7990 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7992 // q3bsp has no lightmap updates, so the lightstylevalue that
7993 // would normally be baked into the lightmap must be
7994 // applied to the color
7995 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7996 if (model->type == mod_brushq3)
7997 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7998 colorscale *= r_refdef.lightmapintensity;
7999 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8000 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8001 // basic lit geometry
8002 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]);
8003 // add pants/shirt if needed
8004 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8005 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]);
8006 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8007 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]);
8008 // now add ambient passes if needed
8009 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8011 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]);
8012 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8013 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]);
8014 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8015 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]);
8018 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8019 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]);
8020 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8022 // if this is opaque use alpha blend which will darken the earlier
8025 // if this is an alpha blended material, all the earlier passes
8026 // were darkened by fog already, so we only need to add the fog
8027 // color ontop through the fog mask texture
8029 // if this is an additive blended material, all the earlier passes
8030 // were darkened by fog already, and we should not add fog color
8031 // (because the background was not darkened, there is no fog color
8032 // that was lost behind it).
8033 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]);
8037 return t->currentframe;
8040 rsurfacestate_t rsurface;
8042 void RSurf_ActiveWorldEntity(void)
8044 dp_model_t *model = r_refdef.scene.worldmodel;
8045 //if (rsurface.entity == r_refdef.scene.worldentity)
8047 rsurface.entity = r_refdef.scene.worldentity;
8048 rsurface.skeleton = NULL;
8049 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8050 rsurface.ent_skinnum = 0;
8051 rsurface.ent_qwskin = -1;
8052 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8053 rsurface.shadertime = r_refdef.scene.time;
8054 rsurface.matrix = identitymatrix;
8055 rsurface.inversematrix = identitymatrix;
8056 rsurface.matrixscale = 1;
8057 rsurface.inversematrixscale = 1;
8058 R_EntityMatrix(&identitymatrix);
8059 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8060 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8061 rsurface.fograngerecip = r_refdef.fograngerecip;
8062 rsurface.fogheightfade = r_refdef.fogheightfade;
8063 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8064 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8065 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8066 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8067 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8068 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8069 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8070 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8071 rsurface.colormod[3] = 1;
8072 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);
8073 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8074 rsurface.frameblend[0].lerp = 1;
8075 rsurface.ent_alttextures = false;
8076 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8077 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8078 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8079 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8081 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8082 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8084 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8085 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8086 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8087 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8088 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8089 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8090 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8091 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8092 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8093 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8094 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8095 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8096 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8097 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8098 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8099 rsurface.modelelement3i = model->surfmesh.data_element3i;
8100 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8101 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8102 rsurface.modelelement3s = model->surfmesh.data_element3s;
8103 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8104 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8105 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8106 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8107 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8108 rsurface.modelsurfaces = model->data_surfaces;
8109 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8110 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8111 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8112 rsurface.modelgeneratedvertex = false;
8113 rsurface.batchgeneratedvertex = false;
8114 rsurface.batchfirstvertex = 0;
8115 rsurface.batchnumvertices = 0;
8116 rsurface.batchfirsttriangle = 0;
8117 rsurface.batchnumtriangles = 0;
8118 rsurface.batchvertex3f = NULL;
8119 rsurface.batchvertex3f_vertexbuffer = NULL;
8120 rsurface.batchvertex3f_bufferoffset = 0;
8121 rsurface.batchsvector3f = NULL;
8122 rsurface.batchsvector3f_vertexbuffer = NULL;
8123 rsurface.batchsvector3f_bufferoffset = 0;
8124 rsurface.batchtvector3f = NULL;
8125 rsurface.batchtvector3f_vertexbuffer = NULL;
8126 rsurface.batchtvector3f_bufferoffset = 0;
8127 rsurface.batchnormal3f = NULL;
8128 rsurface.batchnormal3f_vertexbuffer = NULL;
8129 rsurface.batchnormal3f_bufferoffset = 0;
8130 rsurface.batchlightmapcolor4f = NULL;
8131 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8132 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8133 rsurface.batchtexcoordtexture2f = NULL;
8134 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8135 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8136 rsurface.batchtexcoordlightmap2f = NULL;
8137 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8138 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8139 rsurface.batchvertexmesh = NULL;
8140 rsurface.batchvertexmeshbuffer = NULL;
8141 rsurface.batchvertex3fbuffer = NULL;
8142 rsurface.batchelement3i = NULL;
8143 rsurface.batchelement3i_indexbuffer = NULL;
8144 rsurface.batchelement3i_bufferoffset = 0;
8145 rsurface.batchelement3s = NULL;
8146 rsurface.batchelement3s_indexbuffer = NULL;
8147 rsurface.batchelement3s_bufferoffset = 0;
8148 rsurface.passcolor4f = NULL;
8149 rsurface.passcolor4f_vertexbuffer = NULL;
8150 rsurface.passcolor4f_bufferoffset = 0;
8153 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8155 dp_model_t *model = ent->model;
8156 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8158 rsurface.entity = (entity_render_t *)ent;
8159 rsurface.skeleton = ent->skeleton;
8160 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8161 rsurface.ent_skinnum = ent->skinnum;
8162 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;
8163 rsurface.ent_flags = ent->flags;
8164 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8165 rsurface.matrix = ent->matrix;
8166 rsurface.inversematrix = ent->inversematrix;
8167 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8168 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8169 R_EntityMatrix(&rsurface.matrix);
8170 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8171 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8172 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8173 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8174 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8175 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8176 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8177 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8178 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8179 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8180 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8181 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8182 rsurface.colormod[3] = ent->alpha;
8183 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8184 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8185 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8186 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8187 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8188 if (ent->model->brush.submodel && !prepass)
8190 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8191 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8193 if (model->surfmesh.isanimated && model->AnimateVertices)
8195 if (ent->animcache_vertex3f)
8197 rsurface.modelvertex3f = ent->animcache_vertex3f;
8198 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8199 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8200 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8201 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8202 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8203 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8205 else if (wanttangents)
8207 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8208 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8209 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8210 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8211 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8212 rsurface.modelvertexmesh = NULL;
8213 rsurface.modelvertexmeshbuffer = NULL;
8214 rsurface.modelvertex3fbuffer = NULL;
8216 else if (wantnormals)
8218 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8219 rsurface.modelsvector3f = NULL;
8220 rsurface.modeltvector3f = NULL;
8221 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8222 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8223 rsurface.modelvertexmesh = NULL;
8224 rsurface.modelvertexmeshbuffer = NULL;
8225 rsurface.modelvertex3fbuffer = NULL;
8229 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8230 rsurface.modelsvector3f = NULL;
8231 rsurface.modeltvector3f = NULL;
8232 rsurface.modelnormal3f = NULL;
8233 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8234 rsurface.modelvertexmesh = NULL;
8235 rsurface.modelvertexmeshbuffer = NULL;
8236 rsurface.modelvertex3fbuffer = NULL;
8238 rsurface.modelvertex3f_vertexbuffer = 0;
8239 rsurface.modelvertex3f_bufferoffset = 0;
8240 rsurface.modelsvector3f_vertexbuffer = 0;
8241 rsurface.modelsvector3f_bufferoffset = 0;
8242 rsurface.modeltvector3f_vertexbuffer = 0;
8243 rsurface.modeltvector3f_bufferoffset = 0;
8244 rsurface.modelnormal3f_vertexbuffer = 0;
8245 rsurface.modelnormal3f_bufferoffset = 0;
8246 rsurface.modelgeneratedvertex = true;
8250 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8251 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8253 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8254 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8256 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8257 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8258 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8259 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8260 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8261 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8262 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8263 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8264 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8265 rsurface.modelgeneratedvertex = false;
8267 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8268 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8270 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8271 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8273 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8274 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8275 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8276 rsurface.modelelement3i = model->surfmesh.data_element3i;
8277 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8278 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8279 rsurface.modelelement3s = model->surfmesh.data_element3s;
8280 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8281 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8282 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8283 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8284 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8285 rsurface.modelsurfaces = model->data_surfaces;
8286 rsurface.batchgeneratedvertex = false;
8287 rsurface.batchfirstvertex = 0;
8288 rsurface.batchnumvertices = 0;
8289 rsurface.batchfirsttriangle = 0;
8290 rsurface.batchnumtriangles = 0;
8291 rsurface.batchvertex3f = NULL;
8292 rsurface.batchvertex3f_vertexbuffer = NULL;
8293 rsurface.batchvertex3f_bufferoffset = 0;
8294 rsurface.batchsvector3f = NULL;
8295 rsurface.batchsvector3f_vertexbuffer = NULL;
8296 rsurface.batchsvector3f_bufferoffset = 0;
8297 rsurface.batchtvector3f = NULL;
8298 rsurface.batchtvector3f_vertexbuffer = NULL;
8299 rsurface.batchtvector3f_bufferoffset = 0;
8300 rsurface.batchnormal3f = NULL;
8301 rsurface.batchnormal3f_vertexbuffer = NULL;
8302 rsurface.batchnormal3f_bufferoffset = 0;
8303 rsurface.batchlightmapcolor4f = NULL;
8304 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8305 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8306 rsurface.batchtexcoordtexture2f = NULL;
8307 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8308 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8309 rsurface.batchtexcoordlightmap2f = NULL;
8310 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8311 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8312 rsurface.batchvertexmesh = NULL;
8313 rsurface.batchvertexmeshbuffer = NULL;
8314 rsurface.batchvertex3fbuffer = NULL;
8315 rsurface.batchelement3i = NULL;
8316 rsurface.batchelement3i_indexbuffer = NULL;
8317 rsurface.batchelement3i_bufferoffset = 0;
8318 rsurface.batchelement3s = NULL;
8319 rsurface.batchelement3s_indexbuffer = NULL;
8320 rsurface.batchelement3s_bufferoffset = 0;
8321 rsurface.passcolor4f = NULL;
8322 rsurface.passcolor4f_vertexbuffer = NULL;
8323 rsurface.passcolor4f_bufferoffset = 0;
8326 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)
8328 rsurface.entity = r_refdef.scene.worldentity;
8329 rsurface.skeleton = NULL;
8330 rsurface.ent_skinnum = 0;
8331 rsurface.ent_qwskin = -1;
8332 rsurface.ent_flags = entflags;
8333 rsurface.shadertime = r_refdef.scene.time - shadertime;
8334 rsurface.modelnumvertices = numvertices;
8335 rsurface.modelnumtriangles = numtriangles;
8336 rsurface.matrix = *matrix;
8337 rsurface.inversematrix = *inversematrix;
8338 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8339 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8340 R_EntityMatrix(&rsurface.matrix);
8341 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8342 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8343 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8344 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8345 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8346 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8347 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8348 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8349 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8350 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8351 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8352 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8353 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);
8354 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8355 rsurface.frameblend[0].lerp = 1;
8356 rsurface.ent_alttextures = false;
8357 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8358 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8361 rsurface.modelvertex3f = (float *)vertex3f;
8362 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8363 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8364 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8366 else if (wantnormals)
8368 rsurface.modelvertex3f = (float *)vertex3f;
8369 rsurface.modelsvector3f = NULL;
8370 rsurface.modeltvector3f = NULL;
8371 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8375 rsurface.modelvertex3f = (float *)vertex3f;
8376 rsurface.modelsvector3f = NULL;
8377 rsurface.modeltvector3f = NULL;
8378 rsurface.modelnormal3f = NULL;
8380 rsurface.modelvertexmesh = NULL;
8381 rsurface.modelvertexmeshbuffer = NULL;
8382 rsurface.modelvertex3fbuffer = NULL;
8383 rsurface.modelvertex3f_vertexbuffer = 0;
8384 rsurface.modelvertex3f_bufferoffset = 0;
8385 rsurface.modelsvector3f_vertexbuffer = 0;
8386 rsurface.modelsvector3f_bufferoffset = 0;
8387 rsurface.modeltvector3f_vertexbuffer = 0;
8388 rsurface.modeltvector3f_bufferoffset = 0;
8389 rsurface.modelnormal3f_vertexbuffer = 0;
8390 rsurface.modelnormal3f_bufferoffset = 0;
8391 rsurface.modelgeneratedvertex = true;
8392 rsurface.modellightmapcolor4f = (float *)color4f;
8393 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8394 rsurface.modellightmapcolor4f_bufferoffset = 0;
8395 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8396 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8397 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8398 rsurface.modeltexcoordlightmap2f = NULL;
8399 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8400 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8401 rsurface.modelelement3i = (int *)element3i;
8402 rsurface.modelelement3i_indexbuffer = NULL;
8403 rsurface.modelelement3i_bufferoffset = 0;
8404 rsurface.modelelement3s = (unsigned short *)element3s;
8405 rsurface.modelelement3s_indexbuffer = NULL;
8406 rsurface.modelelement3s_bufferoffset = 0;
8407 rsurface.modellightmapoffsets = NULL;
8408 rsurface.modelsurfaces = NULL;
8409 rsurface.batchgeneratedvertex = false;
8410 rsurface.batchfirstvertex = 0;
8411 rsurface.batchnumvertices = 0;
8412 rsurface.batchfirsttriangle = 0;
8413 rsurface.batchnumtriangles = 0;
8414 rsurface.batchvertex3f = NULL;
8415 rsurface.batchvertex3f_vertexbuffer = NULL;
8416 rsurface.batchvertex3f_bufferoffset = 0;
8417 rsurface.batchsvector3f = NULL;
8418 rsurface.batchsvector3f_vertexbuffer = NULL;
8419 rsurface.batchsvector3f_bufferoffset = 0;
8420 rsurface.batchtvector3f = NULL;
8421 rsurface.batchtvector3f_vertexbuffer = NULL;
8422 rsurface.batchtvector3f_bufferoffset = 0;
8423 rsurface.batchnormal3f = NULL;
8424 rsurface.batchnormal3f_vertexbuffer = NULL;
8425 rsurface.batchnormal3f_bufferoffset = 0;
8426 rsurface.batchlightmapcolor4f = NULL;
8427 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8428 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8429 rsurface.batchtexcoordtexture2f = NULL;
8430 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8431 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8432 rsurface.batchtexcoordlightmap2f = NULL;
8433 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8434 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8435 rsurface.batchvertexmesh = NULL;
8436 rsurface.batchvertexmeshbuffer = NULL;
8437 rsurface.batchvertex3fbuffer = NULL;
8438 rsurface.batchelement3i = NULL;
8439 rsurface.batchelement3i_indexbuffer = NULL;
8440 rsurface.batchelement3i_bufferoffset = 0;
8441 rsurface.batchelement3s = NULL;
8442 rsurface.batchelement3s_indexbuffer = NULL;
8443 rsurface.batchelement3s_bufferoffset = 0;
8444 rsurface.passcolor4f = NULL;
8445 rsurface.passcolor4f_vertexbuffer = NULL;
8446 rsurface.passcolor4f_bufferoffset = 0;
8448 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8450 if ((wantnormals || wanttangents) && !normal3f)
8452 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8453 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8455 if (wanttangents && !svector3f)
8457 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8458 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8459 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8464 float RSurf_FogPoint(const float *v)
8466 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8467 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8468 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8469 float FogHeightFade = r_refdef.fogheightfade;
8471 unsigned int fogmasktableindex;
8472 if (r_refdef.fogplaneviewabove)
8473 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8475 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8476 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8477 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8480 float RSurf_FogVertex(const float *v)
8482 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8483 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8484 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8485 float FogHeightFade = rsurface.fogheightfade;
8487 unsigned int fogmasktableindex;
8488 if (r_refdef.fogplaneviewabove)
8489 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8491 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8492 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8493 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8496 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8499 for (i = 0;i < numelements;i++)
8500 outelement3i[i] = inelement3i[i] + adjust;
8503 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8504 extern cvar_t gl_vbo;
8505 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8513 int surfacefirsttriangle;
8514 int surfacenumtriangles;
8515 int surfacefirstvertex;
8516 int surfaceendvertex;
8517 int surfacenumvertices;
8518 int batchnumvertices;
8519 int batchnumtriangles;
8523 qboolean dynamicvertex;
8527 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8529 q3shaderinfo_deform_t *deform;
8530 const msurface_t *surface, *firstsurface;
8531 r_vertexmesh_t *vertexmesh;
8532 if (!texturenumsurfaces)
8534 // find vertex range of this surface batch
8536 firstsurface = texturesurfacelist[0];
8537 firsttriangle = firstsurface->num_firsttriangle;
8538 batchnumvertices = 0;
8539 batchnumtriangles = 0;
8540 firstvertex = endvertex = firstsurface->num_firstvertex;
8541 for (i = 0;i < texturenumsurfaces;i++)
8543 surface = texturesurfacelist[i];
8544 if (surface != firstsurface + i)
8546 surfacefirstvertex = surface->num_firstvertex;
8547 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8548 surfacenumvertices = surface->num_vertices;
8549 surfacenumtriangles = surface->num_triangles;
8550 if (firstvertex > surfacefirstvertex)
8551 firstvertex = surfacefirstvertex;
8552 if (endvertex < surfaceendvertex)
8553 endvertex = surfaceendvertex;
8554 batchnumvertices += surfacenumvertices;
8555 batchnumtriangles += surfacenumtriangles;
8558 // we now know the vertex range used, and if there are any gaps in it
8559 rsurface.batchfirstvertex = firstvertex;
8560 rsurface.batchnumvertices = endvertex - firstvertex;
8561 rsurface.batchfirsttriangle = firsttriangle;
8562 rsurface.batchnumtriangles = batchnumtriangles;
8564 // this variable holds flags for which properties have been updated that
8565 // may require regenerating vertexmesh array...
8568 // check if any dynamic vertex processing must occur
8569 dynamicvertex = false;
8571 // if there is a chance of animated vertex colors, it's a dynamic batch
8572 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8574 dynamicvertex = true;
8575 batchneed |= BATCHNEED_NOGAPS;
8576 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8579 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8581 switch (deform->deform)
8584 case Q3DEFORM_PROJECTIONSHADOW:
8585 case Q3DEFORM_TEXT0:
8586 case Q3DEFORM_TEXT1:
8587 case Q3DEFORM_TEXT2:
8588 case Q3DEFORM_TEXT3:
8589 case Q3DEFORM_TEXT4:
8590 case Q3DEFORM_TEXT5:
8591 case Q3DEFORM_TEXT6:
8592 case Q3DEFORM_TEXT7:
8595 case Q3DEFORM_AUTOSPRITE:
8596 dynamicvertex = true;
8597 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8598 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8600 case Q3DEFORM_AUTOSPRITE2:
8601 dynamicvertex = true;
8602 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8603 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8605 case Q3DEFORM_NORMAL:
8606 dynamicvertex = true;
8607 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8608 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8611 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8612 break; // if wavefunc is a nop, ignore this transform
8613 dynamicvertex = true;
8614 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8615 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8617 case Q3DEFORM_BULGE:
8618 dynamicvertex = true;
8619 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8620 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8623 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8624 break; // if wavefunc is a nop, ignore this transform
8625 dynamicvertex = true;
8626 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8627 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8631 switch(rsurface.texture->tcgen.tcgen)
8634 case Q3TCGEN_TEXTURE:
8636 case Q3TCGEN_LIGHTMAP:
8637 dynamicvertex = true;
8638 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8639 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8641 case Q3TCGEN_VECTOR:
8642 dynamicvertex = true;
8643 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8644 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8646 case Q3TCGEN_ENVIRONMENT:
8647 dynamicvertex = true;
8648 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8649 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8652 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8654 dynamicvertex = true;
8655 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8659 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8661 dynamicvertex = true;
8662 batchneed |= BATCHNEED_NOGAPS;
8663 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8666 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8668 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8669 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8670 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8671 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8672 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8673 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8674 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8677 // when the model data has no vertex buffer (dynamic mesh), we need to
8679 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8680 batchneed |= BATCHNEED_NOGAPS;
8682 // if needsupdate, we have to do a dynamic vertex batch for sure
8683 if (needsupdate & batchneed)
8684 dynamicvertex = true;
8686 // see if we need to build vertexmesh from arrays
8687 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8688 dynamicvertex = true;
8690 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8691 // also some drivers strongly dislike firstvertex
8692 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8693 dynamicvertex = true;
8695 rsurface.batchvertex3f = rsurface.modelvertex3f;
8696 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8697 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8698 rsurface.batchsvector3f = rsurface.modelsvector3f;
8699 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8700 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8701 rsurface.batchtvector3f = rsurface.modeltvector3f;
8702 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8703 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8704 rsurface.batchnormal3f = rsurface.modelnormal3f;
8705 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8706 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8707 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8708 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8709 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8710 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8711 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8712 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8713 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8714 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8715 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8716 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8717 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8718 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8719 rsurface.batchelement3i = rsurface.modelelement3i;
8720 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8721 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8722 rsurface.batchelement3s = rsurface.modelelement3s;
8723 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8724 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8726 // if any dynamic vertex processing has to occur in software, we copy the
8727 // entire surface list together before processing to rebase the vertices
8728 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8730 // if any gaps exist and we do not have a static vertex buffer, we have to
8731 // copy the surface list together to avoid wasting upload bandwidth on the
8732 // vertices in the gaps.
8734 // if gaps exist and we have a static vertex buffer, we still have to
8735 // combine the index buffer ranges into one dynamic index buffer.
8737 // in all cases we end up with data that can be drawn in one call.
8741 // static vertex data, just set pointers...
8742 rsurface.batchgeneratedvertex = false;
8743 // if there are gaps, we want to build a combined index buffer,
8744 // otherwise use the original static buffer with an appropriate offset
8747 // build a new triangle elements array for this batch
8748 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8749 rsurface.batchfirsttriangle = 0;
8751 for (i = 0;i < texturenumsurfaces;i++)
8753 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8754 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8755 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8756 numtriangles += surfacenumtriangles;
8758 rsurface.batchelement3i_indexbuffer = NULL;
8759 rsurface.batchelement3i_bufferoffset = 0;
8760 rsurface.batchelement3s = NULL;
8761 rsurface.batchelement3s_indexbuffer = NULL;
8762 rsurface.batchelement3s_bufferoffset = 0;
8763 if (endvertex <= 65536)
8765 // make a 16bit (unsigned short) index array if possible
8766 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8767 for (i = 0;i < numtriangles*3;i++)
8768 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8774 // something needs software processing, do it for real...
8775 // we only directly handle separate array data in this case and then
8776 // generate interleaved data if needed...
8777 rsurface.batchgeneratedvertex = true;
8779 // now copy the vertex data into a combined array and make an index array
8780 // (this is what Quake3 does all the time)
8781 //if (gaps || rsurface.batchfirstvertex)
8783 rsurface.batchvertex3fbuffer = NULL;
8784 rsurface.batchvertexmesh = NULL;
8785 rsurface.batchvertexmeshbuffer = NULL;
8786 rsurface.batchvertex3f = NULL;
8787 rsurface.batchvertex3f_vertexbuffer = NULL;
8788 rsurface.batchvertex3f_bufferoffset = 0;
8789 rsurface.batchsvector3f = NULL;
8790 rsurface.batchsvector3f_vertexbuffer = NULL;
8791 rsurface.batchsvector3f_bufferoffset = 0;
8792 rsurface.batchtvector3f = NULL;
8793 rsurface.batchtvector3f_vertexbuffer = NULL;
8794 rsurface.batchtvector3f_bufferoffset = 0;
8795 rsurface.batchnormal3f = NULL;
8796 rsurface.batchnormal3f_vertexbuffer = NULL;
8797 rsurface.batchnormal3f_bufferoffset = 0;
8798 rsurface.batchlightmapcolor4f = NULL;
8799 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8800 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8801 rsurface.batchtexcoordtexture2f = NULL;
8802 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8803 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8804 rsurface.batchtexcoordlightmap2f = NULL;
8805 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8806 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8807 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8808 rsurface.batchelement3i_indexbuffer = NULL;
8809 rsurface.batchelement3i_bufferoffset = 0;
8810 rsurface.batchelement3s = NULL;
8811 rsurface.batchelement3s_indexbuffer = NULL;
8812 rsurface.batchelement3s_bufferoffset = 0;
8813 // we'll only be setting up certain arrays as needed
8814 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8815 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8816 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8817 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8819 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8822 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8823 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8825 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8826 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8827 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8828 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8829 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8830 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8833 for (i = 0;i < texturenumsurfaces;i++)
8835 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8836 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8837 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8838 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8839 // copy only the data requested
8840 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8841 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8842 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8844 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8846 if (rsurface.batchvertex3f)
8847 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8849 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8851 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8853 if (rsurface.modelnormal3f)
8854 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8856 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8858 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8860 if (rsurface.modelsvector3f)
8862 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8863 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8867 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8868 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8871 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8873 if (rsurface.modellightmapcolor4f)
8874 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8876 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8878 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8880 if (rsurface.modeltexcoordtexture2f)
8881 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8883 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8885 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8887 if (rsurface.modeltexcoordlightmap2f)
8888 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8890 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8893 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8894 numvertices += surfacenumvertices;
8895 numtriangles += surfacenumtriangles;
8898 // generate a 16bit index array as well if possible
8899 // (in general, dynamic batches fit)
8900 if (numvertices <= 65536)
8902 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8903 for (i = 0;i < numtriangles*3;i++)
8904 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8907 // since we've copied everything, the batch now starts at 0
8908 rsurface.batchfirstvertex = 0;
8909 rsurface.batchnumvertices = batchnumvertices;
8910 rsurface.batchfirsttriangle = 0;
8911 rsurface.batchnumtriangles = batchnumtriangles;
8914 // q1bsp surfaces rendered in vertex color mode have to have colors
8915 // calculated based on lightstyles
8916 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8918 // generate color arrays for the surfaces in this list
8923 const unsigned char *lm;
8924 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8925 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8926 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8928 for (i = 0;i < texturenumsurfaces;i++)
8930 surface = texturesurfacelist[i];
8931 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8932 surfacenumvertices = surface->num_vertices;
8933 if (surface->lightmapinfo->samples)
8935 for (j = 0;j < surfacenumvertices;j++)
8937 lm = surface->lightmapinfo->samples + offsets[j];
8938 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8939 VectorScale(lm, scale, c);
8940 if (surface->lightmapinfo->styles[1] != 255)
8942 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8944 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8945 VectorMA(c, scale, lm, c);
8946 if (surface->lightmapinfo->styles[2] != 255)
8949 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8950 VectorMA(c, scale, lm, c);
8951 if (surface->lightmapinfo->styles[3] != 255)
8954 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8955 VectorMA(c, scale, lm, c);
8962 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);
8968 for (j = 0;j < surfacenumvertices;j++)
8970 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8977 // if vertices are deformed (sprite flares and things in maps, possibly
8978 // water waves, bulges and other deformations), modify the copied vertices
8980 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8982 switch (deform->deform)
8985 case Q3DEFORM_PROJECTIONSHADOW:
8986 case Q3DEFORM_TEXT0:
8987 case Q3DEFORM_TEXT1:
8988 case Q3DEFORM_TEXT2:
8989 case Q3DEFORM_TEXT3:
8990 case Q3DEFORM_TEXT4:
8991 case Q3DEFORM_TEXT5:
8992 case Q3DEFORM_TEXT6:
8993 case Q3DEFORM_TEXT7:
8996 case Q3DEFORM_AUTOSPRITE:
8997 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8998 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8999 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9000 VectorNormalize(newforward);
9001 VectorNormalize(newright);
9002 VectorNormalize(newup);
9003 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9004 // rsurface.batchvertex3f_vertexbuffer = NULL;
9005 // rsurface.batchvertex3f_bufferoffset = 0;
9006 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9007 // rsurface.batchsvector3f_vertexbuffer = NULL;
9008 // rsurface.batchsvector3f_bufferoffset = 0;
9009 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9010 // rsurface.batchtvector3f_vertexbuffer = NULL;
9011 // rsurface.batchtvector3f_bufferoffset = 0;
9012 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9013 // rsurface.batchnormal3f_vertexbuffer = NULL;
9014 // rsurface.batchnormal3f_bufferoffset = 0;
9015 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9016 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9017 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9018 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9019 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);
9020 // a single autosprite surface can contain multiple sprites...
9021 for (j = 0;j < batchnumvertices - 3;j += 4)
9023 VectorClear(center);
9024 for (i = 0;i < 4;i++)
9025 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9026 VectorScale(center, 0.25f, center);
9027 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9028 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9029 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9030 for (i = 0;i < 4;i++)
9032 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9033 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9036 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9037 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 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);
9040 case Q3DEFORM_AUTOSPRITE2:
9041 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9042 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9043 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9044 VectorNormalize(newforward);
9045 VectorNormalize(newright);
9046 VectorNormalize(newup);
9047 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9048 // rsurface.batchvertex3f_vertexbuffer = NULL;
9049 // rsurface.batchvertex3f_bufferoffset = 0;
9051 const float *v1, *v2;
9061 memset(shortest, 0, sizeof(shortest));
9062 // a single autosprite surface can contain multiple sprites...
9063 for (j = 0;j < batchnumvertices - 3;j += 4)
9065 VectorClear(center);
9066 for (i = 0;i < 4;i++)
9067 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9068 VectorScale(center, 0.25f, center);
9069 // find the two shortest edges, then use them to define the
9070 // axis vectors for rotating around the central axis
9071 for (i = 0;i < 6;i++)
9073 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9074 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9075 l = VectorDistance2(v1, v2);
9076 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9078 l += (1.0f / 1024.0f);
9079 if (shortest[0].length2 > l || i == 0)
9081 shortest[1] = shortest[0];
9082 shortest[0].length2 = l;
9083 shortest[0].v1 = v1;
9084 shortest[0].v2 = v2;
9086 else if (shortest[1].length2 > l || i == 1)
9088 shortest[1].length2 = l;
9089 shortest[1].v1 = v1;
9090 shortest[1].v2 = v2;
9093 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9094 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9095 // this calculates the right vector from the shortest edge
9096 // and the up vector from the edge midpoints
9097 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9098 VectorNormalize(right);
9099 VectorSubtract(end, start, up);
9100 VectorNormalize(up);
9101 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9102 VectorSubtract(rsurface.localvieworigin, center, forward);
9103 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9104 VectorNegate(forward, forward);
9105 VectorReflect(forward, 0, up, forward);
9106 VectorNormalize(forward);
9107 CrossProduct(up, forward, newright);
9108 VectorNormalize(newright);
9109 // rotate the quad around the up axis vector, this is made
9110 // especially easy by the fact we know the quad is flat,
9111 // so we only have to subtract the center position and
9112 // measure distance along the right vector, and then
9113 // multiply that by the newright vector and add back the
9115 // we also need to subtract the old position to undo the
9116 // displacement from the center, which we do with a
9117 // DotProduct, the subtraction/addition of center is also
9118 // optimized into DotProducts here
9119 l = DotProduct(right, center);
9120 for (i = 0;i < 4;i++)
9122 v1 = rsurface.batchvertex3f + 3*(j+i);
9123 f = DotProduct(right, v1) - l;
9124 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9128 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9130 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9131 // rsurface.batchnormal3f_vertexbuffer = NULL;
9132 // rsurface.batchnormal3f_bufferoffset = 0;
9133 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9135 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9137 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9138 // rsurface.batchsvector3f_vertexbuffer = NULL;
9139 // rsurface.batchsvector3f_bufferoffset = 0;
9140 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9141 // rsurface.batchtvector3f_vertexbuffer = NULL;
9142 // rsurface.batchtvector3f_bufferoffset = 0;
9143 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9146 case Q3DEFORM_NORMAL:
9147 // deform the normals to make reflections wavey
9148 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9149 rsurface.batchnormal3f_vertexbuffer = NULL;
9150 rsurface.batchnormal3f_bufferoffset = 0;
9151 for (j = 0;j < batchnumvertices;j++)
9154 float *normal = rsurface.batchnormal3f + 3*j;
9155 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9156 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9157 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9158 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9159 VectorNormalize(normal);
9161 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9163 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 // rsurface.batchsvector3f_vertexbuffer = NULL;
9165 // rsurface.batchsvector3f_bufferoffset = 0;
9166 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9167 // rsurface.batchtvector3f_vertexbuffer = NULL;
9168 // rsurface.batchtvector3f_bufferoffset = 0;
9169 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9173 // deform vertex array to make wavey water and flags and such
9174 waveparms[0] = deform->waveparms[0];
9175 waveparms[1] = deform->waveparms[1];
9176 waveparms[2] = deform->waveparms[2];
9177 waveparms[3] = deform->waveparms[3];
9178 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9179 break; // if wavefunc is a nop, don't make a dynamic vertex array
9180 // this is how a divisor of vertex influence on deformation
9181 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9182 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9183 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9184 // rsurface.batchvertex3f_vertexbuffer = NULL;
9185 // rsurface.batchvertex3f_bufferoffset = 0;
9186 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9187 // rsurface.batchnormal3f_vertexbuffer = NULL;
9188 // rsurface.batchnormal3f_bufferoffset = 0;
9189 for (j = 0;j < batchnumvertices;j++)
9191 // if the wavefunc depends on time, evaluate it per-vertex
9194 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9195 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9197 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9199 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9200 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9201 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9203 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9204 // rsurface.batchsvector3f_vertexbuffer = NULL;
9205 // rsurface.batchsvector3f_bufferoffset = 0;
9206 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9207 // rsurface.batchtvector3f_vertexbuffer = NULL;
9208 // rsurface.batchtvector3f_bufferoffset = 0;
9209 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9212 case Q3DEFORM_BULGE:
9213 // deform vertex array to make the surface have moving bulges
9214 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9215 // rsurface.batchvertex3f_vertexbuffer = NULL;
9216 // rsurface.batchvertex3f_bufferoffset = 0;
9217 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9218 // rsurface.batchnormal3f_vertexbuffer = NULL;
9219 // rsurface.batchnormal3f_bufferoffset = 0;
9220 for (j = 0;j < batchnumvertices;j++)
9222 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9223 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9225 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9226 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9227 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9229 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9230 // rsurface.batchsvector3f_vertexbuffer = NULL;
9231 // rsurface.batchsvector3f_bufferoffset = 0;
9232 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9233 // rsurface.batchtvector3f_vertexbuffer = NULL;
9234 // rsurface.batchtvector3f_bufferoffset = 0;
9235 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);
9239 // deform vertex array
9240 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9241 break; // if wavefunc is a nop, don't make a dynamic vertex array
9242 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9243 VectorScale(deform->parms, scale, waveparms);
9244 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9245 // rsurface.batchvertex3f_vertexbuffer = NULL;
9246 // rsurface.batchvertex3f_bufferoffset = 0;
9247 for (j = 0;j < batchnumvertices;j++)
9248 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9253 // generate texcoords based on the chosen texcoord source
9254 switch(rsurface.texture->tcgen.tcgen)
9257 case Q3TCGEN_TEXTURE:
9259 case Q3TCGEN_LIGHTMAP:
9260 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9261 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9262 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9263 if (rsurface.batchtexcoordlightmap2f)
9264 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9266 case Q3TCGEN_VECTOR:
9267 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9268 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9269 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9270 for (j = 0;j < batchnumvertices;j++)
9272 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9273 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9276 case Q3TCGEN_ENVIRONMENT:
9277 // make environment reflections using a spheremap
9278 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9279 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9280 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9281 for (j = 0;j < batchnumvertices;j++)
9283 // identical to Q3A's method, but executed in worldspace so
9284 // carried models can be shiny too
9286 float viewer[3], d, reflected[3], worldreflected[3];
9288 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9289 // VectorNormalize(viewer);
9291 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9293 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9294 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9295 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9296 // note: this is proportinal to viewer, so we can normalize later
9298 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9299 VectorNormalize(worldreflected);
9301 // note: this sphere map only uses world x and z!
9302 // so positive and negative y will LOOK THE SAME.
9303 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9304 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9308 // the only tcmod that needs software vertex processing is turbulent, so
9309 // check for it here and apply the changes if needed
9310 // and we only support that as the first one
9311 // (handling a mixture of turbulent and other tcmods would be problematic
9312 // without punting it entirely to a software path)
9313 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9315 amplitude = rsurface.texture->tcmods[0].parms[1];
9316 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9317 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9318 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9319 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9320 for (j = 0;j < batchnumvertices;j++)
9322 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);
9323 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9327 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9329 // convert the modified arrays to vertex structs
9330 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9331 // rsurface.batchvertexmeshbuffer = NULL;
9332 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9333 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9334 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9335 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9336 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9337 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9338 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9340 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9342 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9343 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9346 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9347 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9348 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9349 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9350 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9351 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9352 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9353 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9354 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9358 void RSurf_DrawBatch(void)
9360 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9361 // through the pipeline, killing it earlier in the pipeline would have
9362 // per-surface overhead rather than per-batch overhead, so it's best to
9363 // reject it here, before it hits glDraw.
9364 if (rsurface.batchnumtriangles == 0)
9367 // batch debugging code
9368 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9374 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9375 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9378 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9380 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9382 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9383 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);
9390 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);
9393 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9395 // pick the closest matching water plane
9396 int planeindex, vertexindex, bestplaneindex = -1;
9400 r_waterstate_waterplane_t *p;
9401 qboolean prepared = false;
9403 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9405 if(p->camera_entity != rsurface.texture->camera_entity)
9410 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9412 if(rsurface.batchnumvertices == 0)
9415 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9417 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9418 d += fabs(PlaneDiff(vert, &p->plane));
9420 if (bestd > d || bestplaneindex < 0)
9423 bestplaneindex = planeindex;
9426 return bestplaneindex;
9427 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9428 // this situation though, as it might be better to render single larger
9429 // batches with useless stuff (backface culled for example) than to
9430 // render multiple smaller batches
9433 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9436 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9437 rsurface.passcolor4f_vertexbuffer = 0;
9438 rsurface.passcolor4f_bufferoffset = 0;
9439 for (i = 0;i < rsurface.batchnumvertices;i++)
9440 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9443 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9450 if (rsurface.passcolor4f)
9452 // generate color arrays
9453 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9454 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9455 rsurface.passcolor4f_vertexbuffer = 0;
9456 rsurface.passcolor4f_bufferoffset = 0;
9457 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)
9459 f = RSurf_FogVertex(v);
9468 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9469 rsurface.passcolor4f_vertexbuffer = 0;
9470 rsurface.passcolor4f_bufferoffset = 0;
9471 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9473 f = RSurf_FogVertex(v);
9482 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9489 if (!rsurface.passcolor4f)
9491 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9492 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9493 rsurface.passcolor4f_vertexbuffer = 0;
9494 rsurface.passcolor4f_bufferoffset = 0;
9495 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)
9497 f = RSurf_FogVertex(v);
9498 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9499 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9500 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9505 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9510 if (!rsurface.passcolor4f)
9512 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9513 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9514 rsurface.passcolor4f_vertexbuffer = 0;
9515 rsurface.passcolor4f_bufferoffset = 0;
9516 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9525 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9530 if (!rsurface.passcolor4f)
9532 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9533 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9534 rsurface.passcolor4f_vertexbuffer = 0;
9535 rsurface.passcolor4f_bufferoffset = 0;
9536 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9538 c2[0] = c[0] + r_refdef.scene.ambient;
9539 c2[1] = c[1] + r_refdef.scene.ambient;
9540 c2[2] = c[2] + r_refdef.scene.ambient;
9545 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9548 rsurface.passcolor4f = NULL;
9549 rsurface.passcolor4f_vertexbuffer = 0;
9550 rsurface.passcolor4f_bufferoffset = 0;
9551 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9552 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9553 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9554 GL_Color(r, g, b, a);
9555 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9559 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9561 // TODO: optimize applyfog && applycolor case
9562 // just apply fog if necessary, and tint the fog color array if necessary
9563 rsurface.passcolor4f = NULL;
9564 rsurface.passcolor4f_vertexbuffer = 0;
9565 rsurface.passcolor4f_bufferoffset = 0;
9566 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9567 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9568 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9569 GL_Color(r, g, b, a);
9573 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9576 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9577 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9578 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9579 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9580 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9581 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9582 GL_Color(r, g, b, a);
9586 static void RSurf_DrawBatch_GL11_ClampColor(void)
9591 if (!rsurface.passcolor4f)
9593 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9595 c2[0] = bound(0.0f, c1[0], 1.0f);
9596 c2[1] = bound(0.0f, c1[1], 1.0f);
9597 c2[2] = bound(0.0f, c1[2], 1.0f);
9598 c2[3] = bound(0.0f, c1[3], 1.0f);
9602 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9612 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9613 rsurface.passcolor4f_vertexbuffer = 0;
9614 rsurface.passcolor4f_bufferoffset = 0;
9615 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)
9617 f = -DotProduct(r_refdef.view.forward, n);
9619 f = f * 0.85 + 0.15; // work around so stuff won't get black
9620 f *= r_refdef.lightmapintensity;
9621 Vector4Set(c, f, f, f, 1);
9625 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9627 RSurf_DrawBatch_GL11_ApplyFakeLight();
9628 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9629 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9630 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9631 GL_Color(r, g, b, a);
9635 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9643 vec3_t ambientcolor;
9644 vec3_t diffusecolor;
9648 VectorCopy(rsurface.modellight_lightdir, lightdir);
9649 f = 0.5f * r_refdef.lightmapintensity;
9650 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9651 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9652 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9653 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9654 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9655 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9657 if (VectorLength2(diffusecolor) > 0)
9659 // q3-style directional shading
9660 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9661 rsurface.passcolor4f_vertexbuffer = 0;
9662 rsurface.passcolor4f_bufferoffset = 0;
9663 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)
9665 if ((f = DotProduct(n, lightdir)) > 0)
9666 VectorMA(ambientcolor, f, diffusecolor, c);
9668 VectorCopy(ambientcolor, c);
9675 *applycolor = false;
9679 *r = ambientcolor[0];
9680 *g = ambientcolor[1];
9681 *b = ambientcolor[2];
9682 rsurface.passcolor4f = NULL;
9683 rsurface.passcolor4f_vertexbuffer = 0;
9684 rsurface.passcolor4f_bufferoffset = 0;
9688 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9690 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9691 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9692 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9693 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9694 GL_Color(r, g, b, a);
9698 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9706 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9707 rsurface.passcolor4f_vertexbuffer = 0;
9708 rsurface.passcolor4f_bufferoffset = 0;
9710 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9712 f = 1 - RSurf_FogVertex(v);
9720 void RSurf_SetupDepthAndCulling(void)
9722 // submodels are biased to avoid z-fighting with world surfaces that they
9723 // may be exactly overlapping (avoids z-fighting artifacts on certain
9724 // doors and things in Quake maps)
9725 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9726 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9727 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9728 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9731 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9733 // transparent sky would be ridiculous
9734 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9736 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9737 skyrenderlater = true;
9738 RSurf_SetupDepthAndCulling();
9740 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9741 // skymasking on them, and Quake3 never did sky masking (unlike
9742 // software Quake and software Quake2), so disable the sky masking
9743 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9744 // and skymasking also looks very bad when noclipping outside the
9745 // level, so don't use it then either.
9746 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9748 R_Mesh_ResetTextureState();
9749 if (skyrendermasked)
9751 R_SetupShader_DepthOrShadow(false);
9752 // depth-only (masking)
9753 GL_ColorMask(0,0,0,0);
9754 // just to make sure that braindead drivers don't draw
9755 // anything despite that colormask...
9756 GL_BlendFunc(GL_ZERO, GL_ONE);
9757 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9758 if (rsurface.batchvertex3fbuffer)
9759 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9761 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9765 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9767 GL_BlendFunc(GL_ONE, GL_ZERO);
9768 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9769 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9770 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9773 if (skyrendermasked)
9774 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9776 R_Mesh_ResetTextureState();
9777 GL_Color(1, 1, 1, 1);
9780 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9781 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9782 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9784 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9788 // render screenspace normalmap to texture
9790 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9794 // bind lightmap texture
9796 // water/refraction/reflection/camera surfaces have to be handled specially
9797 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9799 int start, end, startplaneindex;
9800 for (start = 0;start < texturenumsurfaces;start = end)
9802 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9803 if(startplaneindex < 0)
9805 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9806 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9810 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9812 // now that we have a batch using the same planeindex, render it
9813 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9815 // render water or distortion background
9817 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);
9819 // blend surface on top
9820 GL_DepthMask(false);
9821 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9824 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9826 // render surface with reflection texture as input
9827 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9828 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);
9835 // render surface batch normally
9836 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9837 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);
9841 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9843 // OpenGL 1.3 path - anything not completely ancient
9844 qboolean applycolor;
9847 const texturelayer_t *layer;
9848 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);
9849 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9851 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9854 int layertexrgbscale;
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 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9869 layertexrgbscale = 4;
9870 VectorScale(layer->color, 0.25f, layercolor);
9872 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9874 layertexrgbscale = 2;
9875 VectorScale(layer->color, 0.5f, layercolor);
9879 layertexrgbscale = 1;
9880 VectorScale(layer->color, 1.0f, layercolor);
9882 layercolor[3] = layer->color[3];
9883 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9884 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9885 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9886 switch (layer->type)
9888 case TEXTURELAYERTYPE_LITTEXTURE:
9889 // single-pass lightmapped texture with 2x rgbscale
9890 R_Mesh_TexBind(0, r_texture_white);
9891 R_Mesh_TexMatrix(0, NULL);
9892 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9893 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9894 R_Mesh_TexBind(1, layer->texture);
9895 R_Mesh_TexMatrix(1, &layer->texmatrix);
9896 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9897 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9898 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9899 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9900 else if (FAKELIGHT_ENABLED)
9901 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9902 else if (rsurface.uselightmaptexture)
9903 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9905 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9907 case TEXTURELAYERTYPE_TEXTURE:
9908 // singletexture unlit texture with transparency support
9909 R_Mesh_TexBind(0, layer->texture);
9910 R_Mesh_TexMatrix(0, &layer->texmatrix);
9911 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9912 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9913 R_Mesh_TexBind(1, 0);
9914 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9915 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, 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, layertexrgbscale, 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 R_Mesh_TexBind(1, 0);
9932 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9933 // generate a color array for the fog pass
9934 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9935 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9939 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9942 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9944 GL_DepthFunc(GL_LEQUAL);
9945 GL_AlphaTest(false);
9949 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9951 // OpenGL 1.1 - crusty old voodoo path
9954 const texturelayer_t *layer;
9955 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);
9956 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9958 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9960 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9962 if (layerindex == 0)
9966 GL_AlphaTest(false);
9967 GL_DepthFunc(GL_EQUAL);
9970 GL_DepthMask(layer->depthmask && writedepth);
9971 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9972 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9973 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9974 switch (layer->type)
9976 case TEXTURELAYERTYPE_LITTEXTURE:
9977 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9979 // two-pass lit texture with 2x rgbscale
9980 // first the lightmap pass
9981 R_Mesh_TexBind(0, r_texture_white);
9982 R_Mesh_TexMatrix(0, NULL);
9983 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9984 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9985 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9986 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9987 else if (FAKELIGHT_ENABLED)
9988 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9989 else if (rsurface.uselightmaptexture)
9990 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9992 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9993 // then apply the texture to it
9994 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9995 R_Mesh_TexBind(0, layer->texture);
9996 R_Mesh_TexMatrix(0, &layer->texmatrix);
9997 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9998 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9999 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);
10003 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10004 R_Mesh_TexBind(0, layer->texture);
10005 R_Mesh_TexMatrix(0, &layer->texmatrix);
10006 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10007 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10008 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10009 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);
10011 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);
10014 case TEXTURELAYERTYPE_TEXTURE:
10015 // singletexture unlit texture with transparency support
10016 R_Mesh_TexBind(0, layer->texture);
10017 R_Mesh_TexMatrix(0, &layer->texmatrix);
10018 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10019 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10020 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);
10022 case TEXTURELAYERTYPE_FOG:
10023 // singletexture fogging
10024 if (layer->texture)
10026 R_Mesh_TexBind(0, layer->texture);
10027 R_Mesh_TexMatrix(0, &layer->texmatrix);
10028 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10029 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10033 R_Mesh_TexBind(0, 0);
10034 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10036 // generate a color array for the fog pass
10037 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10038 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10042 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10047 GL_DepthFunc(GL_LEQUAL);
10048 GL_AlphaTest(false);
10052 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10056 r_vertexgeneric_t *batchvertex;
10059 // R_Mesh_ResetTextureState();
10060 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10062 if(rsurface.texture && rsurface.texture->currentskinframe)
10064 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10065 c[3] *= rsurface.texture->currentalpha;
10075 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10077 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10078 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10079 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10082 // brighten it up (as texture value 127 means "unlit")
10083 c[0] *= 2 * r_refdef.view.colorscale;
10084 c[1] *= 2 * r_refdef.view.colorscale;
10085 c[2] *= 2 * r_refdef.view.colorscale;
10087 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10088 c[3] *= r_wateralpha.value;
10090 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10092 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10093 GL_DepthMask(false);
10095 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10097 GL_BlendFunc(GL_ONE, GL_ONE);
10098 GL_DepthMask(false);
10100 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10102 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10103 GL_DepthMask(false);
10105 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10107 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10108 GL_DepthMask(false);
10112 GL_BlendFunc(GL_ONE, GL_ZERO);
10113 GL_DepthMask(writedepth);
10116 if (r_showsurfaces.integer == 3)
10118 rsurface.passcolor4f = NULL;
10120 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10122 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10124 rsurface.passcolor4f = NULL;
10125 rsurface.passcolor4f_vertexbuffer = 0;
10126 rsurface.passcolor4f_bufferoffset = 0;
10128 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10130 qboolean applycolor = true;
10133 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10135 r_refdef.lightmapintensity = 1;
10136 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10137 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10139 else if (FAKELIGHT_ENABLED)
10141 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10143 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10144 RSurf_DrawBatch_GL11_ApplyFakeLight();
10145 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10149 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10151 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10152 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10153 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10156 if(!rsurface.passcolor4f)
10157 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10159 RSurf_DrawBatch_GL11_ApplyAmbient();
10160 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10161 if(r_refdef.fogenabled)
10162 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10163 RSurf_DrawBatch_GL11_ClampColor();
10165 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10166 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10169 else if (!r_refdef.view.showdebug)
10171 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10172 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10173 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10175 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10176 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10178 R_Mesh_PrepareVertices_Generic_Unlock();
10181 else if (r_showsurfaces.integer == 4)
10183 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10184 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10185 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10187 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10188 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10189 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10191 R_Mesh_PrepareVertices_Generic_Unlock();
10194 else if (r_showsurfaces.integer == 2)
10197 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10198 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10199 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10201 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10202 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10203 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10204 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10205 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10206 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10207 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10209 R_Mesh_PrepareVertices_Generic_Unlock();
10210 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10214 int texturesurfaceindex;
10216 const msurface_t *surface;
10217 float surfacecolor4f[4];
10218 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10219 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10221 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10223 surface = texturesurfacelist[texturesurfaceindex];
10224 k = (int)(((size_t)surface) / sizeof(msurface_t));
10225 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10226 for (j = 0;j < surface->num_vertices;j++)
10228 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10229 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10233 R_Mesh_PrepareVertices_Generic_Unlock();
10238 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10241 RSurf_SetupDepthAndCulling();
10242 if (r_showsurfaces.integer)
10244 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10247 switch (vid.renderpath)
10249 case RENDERPATH_GL20:
10250 case RENDERPATH_D3D9:
10251 case RENDERPATH_D3D10:
10252 case RENDERPATH_D3D11:
10253 case RENDERPATH_SOFT:
10254 case RENDERPATH_GLES2:
10255 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10257 case RENDERPATH_GL13:
10258 case RENDERPATH_GLES1:
10259 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10261 case RENDERPATH_GL11:
10262 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10268 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10271 RSurf_SetupDepthAndCulling();
10272 if (r_showsurfaces.integer)
10274 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10277 switch (vid.renderpath)
10279 case RENDERPATH_GL20:
10280 case RENDERPATH_D3D9:
10281 case RENDERPATH_D3D10:
10282 case RENDERPATH_D3D11:
10283 case RENDERPATH_SOFT:
10284 case RENDERPATH_GLES2:
10285 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10287 case RENDERPATH_GL13:
10288 case RENDERPATH_GLES1:
10289 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10291 case RENDERPATH_GL11:
10292 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10298 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10301 int texturenumsurfaces, endsurface;
10302 texture_t *texture;
10303 const msurface_t *surface;
10304 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10306 // if the model is static it doesn't matter what value we give for
10307 // wantnormals and wanttangents, so this logic uses only rules applicable
10308 // to a model, knowing that they are meaningless otherwise
10309 if (ent == r_refdef.scene.worldentity)
10310 RSurf_ActiveWorldEntity();
10311 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10312 RSurf_ActiveModelEntity(ent, false, false, false);
10315 switch (vid.renderpath)
10317 case RENDERPATH_GL20:
10318 case RENDERPATH_D3D9:
10319 case RENDERPATH_D3D10:
10320 case RENDERPATH_D3D11:
10321 case RENDERPATH_SOFT:
10322 case RENDERPATH_GLES2:
10323 RSurf_ActiveModelEntity(ent, true, true, false);
10325 case RENDERPATH_GL11:
10326 case RENDERPATH_GL13:
10327 case RENDERPATH_GLES1:
10328 RSurf_ActiveModelEntity(ent, true, false, false);
10333 if (r_transparentdepthmasking.integer)
10335 qboolean setup = false;
10336 for (i = 0;i < numsurfaces;i = j)
10339 surface = rsurface.modelsurfaces + surfacelist[i];
10340 texture = surface->texture;
10341 rsurface.texture = R_GetCurrentTexture(texture);
10342 rsurface.lightmaptexture = NULL;
10343 rsurface.deluxemaptexture = NULL;
10344 rsurface.uselightmaptexture = false;
10345 // scan ahead until we find a different texture
10346 endsurface = min(i + 1024, numsurfaces);
10347 texturenumsurfaces = 0;
10348 texturesurfacelist[texturenumsurfaces++] = surface;
10349 for (;j < endsurface;j++)
10351 surface = rsurface.modelsurfaces + surfacelist[j];
10352 if (texture != surface->texture)
10354 texturesurfacelist[texturenumsurfaces++] = surface;
10356 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10358 // render the range of surfaces as depth
10362 GL_ColorMask(0,0,0,0);
10364 GL_DepthTest(true);
10365 GL_BlendFunc(GL_ONE, GL_ZERO);
10366 GL_DepthMask(true);
10367 // R_Mesh_ResetTextureState();
10368 R_SetupShader_DepthOrShadow(false);
10370 RSurf_SetupDepthAndCulling();
10371 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10372 if (rsurface.batchvertex3fbuffer)
10373 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10375 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10379 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10382 for (i = 0;i < numsurfaces;i = j)
10385 surface = rsurface.modelsurfaces + surfacelist[i];
10386 texture = surface->texture;
10387 rsurface.texture = R_GetCurrentTexture(texture);
10388 // scan ahead until we find a different texture
10389 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10390 texturenumsurfaces = 0;
10391 texturesurfacelist[texturenumsurfaces++] = surface;
10392 if(FAKELIGHT_ENABLED)
10394 rsurface.lightmaptexture = NULL;
10395 rsurface.deluxemaptexture = NULL;
10396 rsurface.uselightmaptexture = false;
10397 for (;j < endsurface;j++)
10399 surface = rsurface.modelsurfaces + surfacelist[j];
10400 if (texture != surface->texture)
10402 texturesurfacelist[texturenumsurfaces++] = surface;
10407 rsurface.lightmaptexture = surface->lightmaptexture;
10408 rsurface.deluxemaptexture = surface->deluxemaptexture;
10409 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10410 for (;j < endsurface;j++)
10412 surface = rsurface.modelsurfaces + surfacelist[j];
10413 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10415 texturesurfacelist[texturenumsurfaces++] = surface;
10418 // render the range of surfaces
10419 if (ent == r_refdef.scene.worldentity)
10420 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10422 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10424 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10427 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10429 // transparent surfaces get pushed off into the transparent queue
10430 int surfacelistindex;
10431 const msurface_t *surface;
10432 vec3_t tempcenter, center;
10433 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10435 surface = texturesurfacelist[surfacelistindex];
10436 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10437 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10438 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10439 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10440 if (queueentity->transparent_offset) // transparent offset
10442 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10443 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10444 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10446 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10450 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10452 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10454 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10456 RSurf_SetupDepthAndCulling();
10457 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10458 if (rsurface.batchvertex3fbuffer)
10459 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10461 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10465 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10467 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10470 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10473 if (!rsurface.texture->currentnumlayers)
10475 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10476 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10478 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10480 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10481 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10482 else if (!rsurface.texture->currentnumlayers)
10484 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10486 // in the deferred case, transparent surfaces were queued during prepass
10487 if (!r_shadow_usingdeferredprepass)
10488 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10492 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10493 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10498 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10501 texture_t *texture;
10502 R_FrameData_SetMark();
10503 // break the surface list down into batches by texture and use of lightmapping
10504 for (i = 0;i < numsurfaces;i = j)
10507 // texture is the base texture pointer, rsurface.texture is the
10508 // current frame/skin the texture is directing us to use (for example
10509 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10510 // use skin 1 instead)
10511 texture = surfacelist[i]->texture;
10512 rsurface.texture = R_GetCurrentTexture(texture);
10513 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10515 // if this texture is not the kind we want, skip ahead to the next one
10516 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10520 if(FAKELIGHT_ENABLED || depthonly || prepass)
10522 rsurface.lightmaptexture = NULL;
10523 rsurface.deluxemaptexture = NULL;
10524 rsurface.uselightmaptexture = false;
10525 // simply scan ahead until we find a different texture or lightmap state
10526 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10531 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10532 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10533 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10534 // simply scan ahead until we find a different texture or lightmap state
10535 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10538 // render the range of surfaces
10539 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10541 R_FrameData_ReturnToMark();
10544 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10548 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10551 if (!rsurface.texture->currentnumlayers)
10553 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10554 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10556 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10558 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10559 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10560 else if (!rsurface.texture->currentnumlayers)
10562 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10564 // in the deferred case, transparent surfaces were queued during prepass
10565 if (!r_shadow_usingdeferredprepass)
10566 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10570 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10571 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10576 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10579 texture_t *texture;
10580 R_FrameData_SetMark();
10581 // break the surface list down into batches by texture and use of lightmapping
10582 for (i = 0;i < numsurfaces;i = j)
10585 // texture is the base texture pointer, rsurface.texture is the
10586 // current frame/skin the texture is directing us to use (for example
10587 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10588 // use skin 1 instead)
10589 texture = surfacelist[i]->texture;
10590 rsurface.texture = R_GetCurrentTexture(texture);
10591 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10593 // if this texture is not the kind we want, skip ahead to the next one
10594 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10598 if(FAKELIGHT_ENABLED || depthonly || prepass)
10600 rsurface.lightmaptexture = NULL;
10601 rsurface.deluxemaptexture = NULL;
10602 rsurface.uselightmaptexture = false;
10603 // simply scan ahead until we find a different texture or lightmap state
10604 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10609 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10610 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10611 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10612 // simply scan ahead until we find a different texture or lightmap state
10613 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10616 // render the range of surfaces
10617 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10619 R_FrameData_ReturnToMark();
10622 float locboxvertex3f[6*4*3] =
10624 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10625 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10626 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10627 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10628 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10629 1,0,0, 0,0,0, 0,1,0, 1,1,0
10632 unsigned short locboxelements[6*2*3] =
10637 12,13,14, 12,14,15,
10638 16,17,18, 16,18,19,
10642 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10645 cl_locnode_t *loc = (cl_locnode_t *)ent;
10647 float vertex3f[6*4*3];
10649 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10650 GL_DepthMask(false);
10651 GL_DepthRange(0, 1);
10652 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10653 GL_DepthTest(true);
10654 GL_CullFace(GL_NONE);
10655 R_EntityMatrix(&identitymatrix);
10657 // R_Mesh_ResetTextureState();
10659 i = surfacelist[0];
10660 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10661 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10662 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10663 surfacelist[0] < 0 ? 0.5f : 0.125f);
10665 if (VectorCompare(loc->mins, loc->maxs))
10667 VectorSet(size, 2, 2, 2);
10668 VectorMA(loc->mins, -0.5f, size, mins);
10672 VectorCopy(loc->mins, mins);
10673 VectorSubtract(loc->maxs, loc->mins, size);
10676 for (i = 0;i < 6*4*3;)
10677 for (j = 0;j < 3;j++, i++)
10678 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10680 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10681 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10682 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10685 void R_DrawLocs(void)
10688 cl_locnode_t *loc, *nearestloc;
10690 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10691 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10693 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10694 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10698 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10700 if (decalsystem->decals)
10701 Mem_Free(decalsystem->decals);
10702 memset(decalsystem, 0, sizeof(*decalsystem));
10705 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)
10708 tridecal_t *decals;
10711 // expand or initialize the system
10712 if (decalsystem->maxdecals <= decalsystem->numdecals)
10714 decalsystem_t old = *decalsystem;
10715 qboolean useshortelements;
10716 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10717 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10718 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)));
10719 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10720 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10721 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10722 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10723 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10724 if (decalsystem->numdecals)
10725 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10727 Mem_Free(old.decals);
10728 for (i = 0;i < decalsystem->maxdecals*3;i++)
10729 decalsystem->element3i[i] = i;
10730 if (useshortelements)
10731 for (i = 0;i < decalsystem->maxdecals*3;i++)
10732 decalsystem->element3s[i] = i;
10735 // grab a decal and search for another free slot for the next one
10736 decals = decalsystem->decals;
10737 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10738 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10740 decalsystem->freedecal = i;
10741 if (decalsystem->numdecals <= i)
10742 decalsystem->numdecals = i + 1;
10744 // initialize the decal
10746 decal->triangleindex = triangleindex;
10747 decal->surfaceindex = surfaceindex;
10748 decal->decalsequence = decalsequence;
10749 decal->color4f[0][0] = c0[0];
10750 decal->color4f[0][1] = c0[1];
10751 decal->color4f[0][2] = c0[2];
10752 decal->color4f[0][3] = 1;
10753 decal->color4f[1][0] = c1[0];
10754 decal->color4f[1][1] = c1[1];
10755 decal->color4f[1][2] = c1[2];
10756 decal->color4f[1][3] = 1;
10757 decal->color4f[2][0] = c2[0];
10758 decal->color4f[2][1] = c2[1];
10759 decal->color4f[2][2] = c2[2];
10760 decal->color4f[2][3] = 1;
10761 decal->vertex3f[0][0] = v0[0];
10762 decal->vertex3f[0][1] = v0[1];
10763 decal->vertex3f[0][2] = v0[2];
10764 decal->vertex3f[1][0] = v1[0];
10765 decal->vertex3f[1][1] = v1[1];
10766 decal->vertex3f[1][2] = v1[2];
10767 decal->vertex3f[2][0] = v2[0];
10768 decal->vertex3f[2][1] = v2[1];
10769 decal->vertex3f[2][2] = v2[2];
10770 decal->texcoord2f[0][0] = t0[0];
10771 decal->texcoord2f[0][1] = t0[1];
10772 decal->texcoord2f[1][0] = t1[0];
10773 decal->texcoord2f[1][1] = t1[1];
10774 decal->texcoord2f[2][0] = t2[0];
10775 decal->texcoord2f[2][1] = t2[1];
10776 TriangleNormal(v0, v1, v2, decal->plane);
10777 VectorNormalize(decal->plane);
10778 decal->plane[3] = DotProduct(v0, decal->plane);
10781 extern cvar_t cl_decals_bias;
10782 extern cvar_t cl_decals_models;
10783 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10784 // baseparms, parms, temps
10785 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)
10790 const float *vertex3f;
10791 const float *normal3f;
10793 float points[2][9][3];
10800 e = rsurface.modelelement3i + 3*triangleindex;
10802 vertex3f = rsurface.modelvertex3f;
10803 normal3f = rsurface.modelnormal3f;
10807 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10809 index = 3*e[cornerindex];
10810 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10815 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10817 index = 3*e[cornerindex];
10818 VectorCopy(vertex3f + index, v[cornerindex]);
10823 //TriangleNormal(v[0], v[1], v[2], normal);
10824 //if (DotProduct(normal, localnormal) < 0.0f)
10826 // clip by each of the box planes formed from the projection matrix
10827 // if anything survives, we emit the decal
10828 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]);
10831 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]);
10834 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]);
10837 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]);
10840 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]);
10843 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]);
10846 // some part of the triangle survived, so we have to accept it...
10849 // dynamic always uses the original triangle
10851 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10853 index = 3*e[cornerindex];
10854 VectorCopy(vertex3f + index, v[cornerindex]);
10857 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10859 // convert vertex positions to texcoords
10860 Matrix4x4_Transform(projection, v[cornerindex], temp);
10861 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10862 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10863 // calculate distance fade from the projection origin
10864 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10865 f = bound(0.0f, f, 1.0f);
10866 c[cornerindex][0] = r * f;
10867 c[cornerindex][1] = g * f;
10868 c[cornerindex][2] = b * f;
10869 c[cornerindex][3] = 1.0f;
10870 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10873 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);
10875 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10876 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);
10878 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)
10880 matrix4x4_t projection;
10881 decalsystem_t *decalsystem;
10884 const msurface_t *surface;
10885 const msurface_t *surfaces;
10886 const int *surfacelist;
10887 const texture_t *texture;
10889 int numsurfacelist;
10890 int surfacelistindex;
10893 float localorigin[3];
10894 float localnormal[3];
10895 float localmins[3];
10896 float localmaxs[3];
10899 float planes[6][4];
10902 int bih_triangles_count;
10903 int bih_triangles[256];
10904 int bih_surfaces[256];
10906 decalsystem = &ent->decalsystem;
10907 model = ent->model;
10908 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10910 R_DecalSystem_Reset(&ent->decalsystem);
10914 if (!model->brush.data_leafs && !cl_decals_models.integer)
10916 if (decalsystem->model)
10917 R_DecalSystem_Reset(decalsystem);
10921 if (decalsystem->model != model)
10922 R_DecalSystem_Reset(decalsystem);
10923 decalsystem->model = model;
10925 RSurf_ActiveModelEntity(ent, true, false, false);
10927 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10928 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10929 VectorNormalize(localnormal);
10930 localsize = worldsize*rsurface.inversematrixscale;
10931 localmins[0] = localorigin[0] - localsize;
10932 localmins[1] = localorigin[1] - localsize;
10933 localmins[2] = localorigin[2] - localsize;
10934 localmaxs[0] = localorigin[0] + localsize;
10935 localmaxs[1] = localorigin[1] + localsize;
10936 localmaxs[2] = localorigin[2] + localsize;
10938 //VectorCopy(localnormal, planes[4]);
10939 //VectorVectors(planes[4], planes[2], planes[0]);
10940 AnglesFromVectors(angles, localnormal, NULL, false);
10941 AngleVectors(angles, planes[0], planes[2], planes[4]);
10942 VectorNegate(planes[0], planes[1]);
10943 VectorNegate(planes[2], planes[3]);
10944 VectorNegate(planes[4], planes[5]);
10945 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10946 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10947 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10948 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10949 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10950 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10955 matrix4x4_t forwardprojection;
10956 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10957 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10962 float projectionvector[4][3];
10963 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10964 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10965 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10966 projectionvector[0][0] = planes[0][0] * ilocalsize;
10967 projectionvector[0][1] = planes[1][0] * ilocalsize;
10968 projectionvector[0][2] = planes[2][0] * ilocalsize;
10969 projectionvector[1][0] = planes[0][1] * ilocalsize;
10970 projectionvector[1][1] = planes[1][1] * ilocalsize;
10971 projectionvector[1][2] = planes[2][1] * ilocalsize;
10972 projectionvector[2][0] = planes[0][2] * ilocalsize;
10973 projectionvector[2][1] = planes[1][2] * ilocalsize;
10974 projectionvector[2][2] = planes[2][2] * ilocalsize;
10975 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10976 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10977 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10978 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10982 dynamic = model->surfmesh.isanimated;
10983 numsurfacelist = model->nummodelsurfaces;
10984 surfacelist = model->sortedmodelsurfaces;
10985 surfaces = model->data_surfaces;
10988 bih_triangles_count = -1;
10991 if(model->render_bih.numleafs)
10992 bih = &model->render_bih;
10993 else if(model->collision_bih.numleafs)
10994 bih = &model->collision_bih;
10997 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10998 if(bih_triangles_count == 0)
11000 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11002 if(bih_triangles_count > 0)
11004 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11006 surfaceindex = bih_surfaces[triangleindex];
11007 surface = surfaces + surfaceindex;
11008 texture = surface->texture;
11009 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11011 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11013 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11018 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11020 surfaceindex = surfacelist[surfacelistindex];
11021 surface = surfaces + surfaceindex;
11022 // check cull box first because it rejects more than any other check
11023 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11025 // skip transparent surfaces
11026 texture = surface->texture;
11027 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11029 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11031 numtriangles = surface->num_triangles;
11032 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11033 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11038 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11039 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)
11041 int renderentityindex;
11042 float worldmins[3];
11043 float worldmaxs[3];
11044 entity_render_t *ent;
11046 if (!cl_decals_newsystem.integer)
11049 worldmins[0] = worldorigin[0] - worldsize;
11050 worldmins[1] = worldorigin[1] - worldsize;
11051 worldmins[2] = worldorigin[2] - worldsize;
11052 worldmaxs[0] = worldorigin[0] + worldsize;
11053 worldmaxs[1] = worldorigin[1] + worldsize;
11054 worldmaxs[2] = worldorigin[2] + worldsize;
11056 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11058 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11060 ent = r_refdef.scene.entities[renderentityindex];
11061 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11064 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11068 typedef struct r_decalsystem_splatqueue_s
11070 vec3_t worldorigin;
11071 vec3_t worldnormal;
11077 r_decalsystem_splatqueue_t;
11079 int r_decalsystem_numqueued = 0;
11080 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11082 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)
11084 r_decalsystem_splatqueue_t *queue;
11086 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11089 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11090 VectorCopy(worldorigin, queue->worldorigin);
11091 VectorCopy(worldnormal, queue->worldnormal);
11092 Vector4Set(queue->color, r, g, b, a);
11093 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11094 queue->worldsize = worldsize;
11095 queue->decalsequence = cl.decalsequence++;
11098 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11101 r_decalsystem_splatqueue_t *queue;
11103 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11104 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);
11105 r_decalsystem_numqueued = 0;
11108 extern cvar_t cl_decals_max;
11109 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11112 decalsystem_t *decalsystem = &ent->decalsystem;
11119 if (!decalsystem->numdecals)
11122 if (r_showsurfaces.integer)
11125 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11127 R_DecalSystem_Reset(decalsystem);
11131 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11132 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11134 if (decalsystem->lastupdatetime)
11135 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11138 decalsystem->lastupdatetime = r_refdef.scene.time;
11139 decal = decalsystem->decals;
11140 numdecals = decalsystem->numdecals;
11142 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11144 if (decal->color4f[0][3])
11146 decal->lived += frametime;
11147 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11149 memset(decal, 0, sizeof(*decal));
11150 if (decalsystem->freedecal > i)
11151 decalsystem->freedecal = i;
11155 decal = decalsystem->decals;
11156 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11159 // collapse the array by shuffling the tail decals into the gaps
11162 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11163 decalsystem->freedecal++;
11164 if (decalsystem->freedecal == numdecals)
11166 decal[decalsystem->freedecal] = decal[--numdecals];
11169 decalsystem->numdecals = numdecals;
11171 if (numdecals <= 0)
11173 // if there are no decals left, reset decalsystem
11174 R_DecalSystem_Reset(decalsystem);
11178 extern skinframe_t *decalskinframe;
11179 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11182 decalsystem_t *decalsystem = &ent->decalsystem;
11191 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11194 numdecals = decalsystem->numdecals;
11198 if (r_showsurfaces.integer)
11201 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11203 R_DecalSystem_Reset(decalsystem);
11207 // if the model is static it doesn't matter what value we give for
11208 // wantnormals and wanttangents, so this logic uses only rules applicable
11209 // to a model, knowing that they are meaningless otherwise
11210 if (ent == r_refdef.scene.worldentity)
11211 RSurf_ActiveWorldEntity();
11213 RSurf_ActiveModelEntity(ent, false, false, false);
11215 decalsystem->lastupdatetime = r_refdef.scene.time;
11216 decal = decalsystem->decals;
11218 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11220 // update vertex positions for animated models
11221 v3f = decalsystem->vertex3f;
11222 c4f = decalsystem->color4f;
11223 t2f = decalsystem->texcoord2f;
11224 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11226 if (!decal->color4f[0][3])
11229 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11233 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11236 // update color values for fading decals
11237 if (decal->lived >= cl_decals_time.value)
11238 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11242 c4f[ 0] = decal->color4f[0][0] * alpha;
11243 c4f[ 1] = decal->color4f[0][1] * alpha;
11244 c4f[ 2] = decal->color4f[0][2] * alpha;
11246 c4f[ 4] = decal->color4f[1][0] * alpha;
11247 c4f[ 5] = decal->color4f[1][1] * alpha;
11248 c4f[ 6] = decal->color4f[1][2] * alpha;
11250 c4f[ 8] = decal->color4f[2][0] * alpha;
11251 c4f[ 9] = decal->color4f[2][1] * alpha;
11252 c4f[10] = decal->color4f[2][2] * alpha;
11255 t2f[0] = decal->texcoord2f[0][0];
11256 t2f[1] = decal->texcoord2f[0][1];
11257 t2f[2] = decal->texcoord2f[1][0];
11258 t2f[3] = decal->texcoord2f[1][1];
11259 t2f[4] = decal->texcoord2f[2][0];
11260 t2f[5] = decal->texcoord2f[2][1];
11262 // update vertex positions for animated models
11263 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11265 e = rsurface.modelelement3i + 3*decal->triangleindex;
11266 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11267 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11268 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11272 VectorCopy(decal->vertex3f[0], v3f);
11273 VectorCopy(decal->vertex3f[1], v3f + 3);
11274 VectorCopy(decal->vertex3f[2], v3f + 6);
11277 if (r_refdef.fogenabled)
11279 alpha = RSurf_FogVertex(v3f);
11280 VectorScale(c4f, alpha, c4f);
11281 alpha = RSurf_FogVertex(v3f + 3);
11282 VectorScale(c4f + 4, alpha, c4f + 4);
11283 alpha = RSurf_FogVertex(v3f + 6);
11284 VectorScale(c4f + 8, alpha, c4f + 8);
11295 r_refdef.stats.drawndecals += numtris;
11297 // now render the decals all at once
11298 // (this assumes they all use one particle font texture!)
11299 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);
11300 // R_Mesh_ResetTextureState();
11301 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11302 GL_DepthMask(false);
11303 GL_DepthRange(0, 1);
11304 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11305 GL_DepthTest(true);
11306 GL_CullFace(GL_NONE);
11307 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11308 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11309 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11313 static void R_DrawModelDecals(void)
11317 // fade faster when there are too many decals
11318 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11319 for (i = 0;i < r_refdef.scene.numentities;i++)
11320 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11322 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11323 for (i = 0;i < r_refdef.scene.numentities;i++)
11324 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11325 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11327 R_DecalSystem_ApplySplatEntitiesQueue();
11329 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11330 for (i = 0;i < r_refdef.scene.numentities;i++)
11331 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11333 r_refdef.stats.totaldecals += numdecals;
11335 if (r_showsurfaces.integer)
11338 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11340 for (i = 0;i < r_refdef.scene.numentities;i++)
11342 if (!r_refdef.viewcache.entityvisible[i])
11344 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11345 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11349 extern cvar_t mod_collision_bih;
11350 void R_DrawDebugModel(void)
11352 entity_render_t *ent = rsurface.entity;
11353 int i, j, k, l, flagsmask;
11354 const msurface_t *surface;
11355 dp_model_t *model = ent->model;
11358 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11361 if (r_showoverdraw.value > 0)
11363 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11364 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11365 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11366 GL_DepthTest(false);
11367 GL_DepthMask(false);
11368 GL_DepthRange(0, 1);
11369 GL_BlendFunc(GL_ONE, GL_ONE);
11370 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11372 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11374 rsurface.texture = R_GetCurrentTexture(surface->texture);
11375 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11377 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11378 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11379 if (!rsurface.texture->currentlayers->depthmask)
11380 GL_Color(c, 0, 0, 1.0f);
11381 else if (ent == r_refdef.scene.worldentity)
11382 GL_Color(c, c, c, 1.0f);
11384 GL_Color(0, c, 0, 1.0f);
11385 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11389 rsurface.texture = NULL;
11392 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11394 // R_Mesh_ResetTextureState();
11395 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11396 GL_DepthRange(0, 1);
11397 GL_DepthTest(!r_showdisabledepthtest.integer);
11398 GL_DepthMask(false);
11399 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11401 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11405 qboolean cullbox = ent == r_refdef.scene.worldentity;
11406 const q3mbrush_t *brush;
11407 const bih_t *bih = &model->collision_bih;
11408 const bih_leaf_t *bihleaf;
11409 float vertex3f[3][3];
11410 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11412 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11414 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11416 switch (bihleaf->type)
11419 brush = model->brush.data_brushes + bihleaf->itemindex;
11420 if (brush->colbrushf && brush->colbrushf->numtriangles)
11422 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);
11423 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11424 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11427 case BIH_COLLISIONTRIANGLE:
11428 triangleindex = bihleaf->itemindex;
11429 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11430 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11431 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11432 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);
11433 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11434 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11436 case BIH_RENDERTRIANGLE:
11437 triangleindex = bihleaf->itemindex;
11438 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11439 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11440 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11441 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);
11442 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11443 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11449 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11452 if (r_showtris.integer && qglPolygonMode)
11454 if (r_showdisabledepthtest.integer)
11456 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11457 GL_DepthMask(false);
11461 GL_BlendFunc(GL_ONE, GL_ZERO);
11462 GL_DepthMask(true);
11464 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11465 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11467 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11469 rsurface.texture = R_GetCurrentTexture(surface->texture);
11470 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11472 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11473 if (!rsurface.texture->currentlayers->depthmask)
11474 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11475 else if (ent == r_refdef.scene.worldentity)
11476 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11478 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11479 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11483 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11484 rsurface.texture = NULL;
11487 if (r_shownormals.value != 0 && qglBegin)
11489 if (r_showdisabledepthtest.integer)
11491 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11492 GL_DepthMask(false);
11496 GL_BlendFunc(GL_ONE, GL_ZERO);
11497 GL_DepthMask(true);
11499 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11501 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11503 rsurface.texture = R_GetCurrentTexture(surface->texture);
11504 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11506 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11507 qglBegin(GL_LINES);
11508 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11510 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11512 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11513 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11514 qglVertex3f(v[0], v[1], v[2]);
11515 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11516 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11517 qglVertex3f(v[0], v[1], v[2]);
11520 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11522 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11524 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11525 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11526 qglVertex3f(v[0], v[1], v[2]);
11527 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11528 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11529 qglVertex3f(v[0], v[1], v[2]);
11532 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11534 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11536 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11537 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11538 qglVertex3f(v[0], v[1], v[2]);
11539 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11540 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11541 qglVertex3f(v[0], v[1], v[2]);
11544 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11546 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11548 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11549 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11550 qglVertex3f(v[0], v[1], v[2]);
11551 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11552 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11553 qglVertex3f(v[0], v[1], v[2]);
11560 rsurface.texture = NULL;
11565 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11566 int r_maxsurfacelist = 0;
11567 const msurface_t **r_surfacelist = NULL;
11568 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11570 int i, j, endj, flagsmask;
11571 dp_model_t *model = r_refdef.scene.worldmodel;
11572 msurface_t *surfaces;
11573 unsigned char *update;
11574 int numsurfacelist = 0;
11578 if (r_maxsurfacelist < model->num_surfaces)
11580 r_maxsurfacelist = model->num_surfaces;
11582 Mem_Free((msurface_t**)r_surfacelist);
11583 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11586 RSurf_ActiveWorldEntity();
11588 surfaces = model->data_surfaces;
11589 update = model->brushq1.lightmapupdateflags;
11591 // update light styles on this submodel
11592 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11594 model_brush_lightstyleinfo_t *style;
11595 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11597 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11599 int *list = style->surfacelist;
11600 style->value = r_refdef.scene.lightstylevalue[style->style];
11601 for (j = 0;j < style->numsurfaces;j++)
11602 update[list[j]] = true;
11607 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11611 R_DrawDebugModel();
11612 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11616 rsurface.lightmaptexture = NULL;
11617 rsurface.deluxemaptexture = NULL;
11618 rsurface.uselightmaptexture = false;
11619 rsurface.texture = NULL;
11620 rsurface.rtlight = NULL;
11621 numsurfacelist = 0;
11622 // add visible surfaces to draw list
11623 for (i = 0;i < model->nummodelsurfaces;i++)
11625 j = model->sortedmodelsurfaces[i];
11626 if (r_refdef.viewcache.world_surfacevisible[j])
11627 r_surfacelist[numsurfacelist++] = surfaces + j;
11629 // update lightmaps if needed
11630 if (model->brushq1.firstrender)
11632 model->brushq1.firstrender = false;
11633 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11635 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11639 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11640 if (r_refdef.viewcache.world_surfacevisible[j])
11642 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11644 // don't do anything if there were no surfaces
11645 if (!numsurfacelist)
11647 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11650 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11652 // add to stats if desired
11653 if (r_speeds.integer && !skysurfaces && !depthonly)
11655 r_refdef.stats.world_surfaces += numsurfacelist;
11656 for (j = 0;j < numsurfacelist;j++)
11657 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11660 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11663 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11665 int i, j, endj, flagsmask;
11666 dp_model_t *model = ent->model;
11667 msurface_t *surfaces;
11668 unsigned char *update;
11669 int numsurfacelist = 0;
11673 if (r_maxsurfacelist < model->num_surfaces)
11675 r_maxsurfacelist = model->num_surfaces;
11677 Mem_Free((msurface_t **)r_surfacelist);
11678 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11681 // if the model is static it doesn't matter what value we give for
11682 // wantnormals and wanttangents, so this logic uses only rules applicable
11683 // to a model, knowing that they are meaningless otherwise
11684 if (ent == r_refdef.scene.worldentity)
11685 RSurf_ActiveWorldEntity();
11686 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11687 RSurf_ActiveModelEntity(ent, false, false, false);
11689 RSurf_ActiveModelEntity(ent, true, true, true);
11690 else if (depthonly)
11692 switch (vid.renderpath)
11694 case RENDERPATH_GL20:
11695 case RENDERPATH_D3D9:
11696 case RENDERPATH_D3D10:
11697 case RENDERPATH_D3D11:
11698 case RENDERPATH_SOFT:
11699 case RENDERPATH_GLES2:
11700 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11702 case RENDERPATH_GL11:
11703 case RENDERPATH_GL13:
11704 case RENDERPATH_GLES1:
11705 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11711 switch (vid.renderpath)
11713 case RENDERPATH_GL20:
11714 case RENDERPATH_D3D9:
11715 case RENDERPATH_D3D10:
11716 case RENDERPATH_D3D11:
11717 case RENDERPATH_SOFT:
11718 case RENDERPATH_GLES2:
11719 RSurf_ActiveModelEntity(ent, true, true, false);
11721 case RENDERPATH_GL11:
11722 case RENDERPATH_GL13:
11723 case RENDERPATH_GLES1:
11724 RSurf_ActiveModelEntity(ent, true, false, false);
11729 surfaces = model->data_surfaces;
11730 update = model->brushq1.lightmapupdateflags;
11732 // update light styles
11733 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11735 model_brush_lightstyleinfo_t *style;
11736 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11738 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11740 int *list = style->surfacelist;
11741 style->value = r_refdef.scene.lightstylevalue[style->style];
11742 for (j = 0;j < style->numsurfaces;j++)
11743 update[list[j]] = true;
11748 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11752 R_DrawDebugModel();
11753 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11757 rsurface.lightmaptexture = NULL;
11758 rsurface.deluxemaptexture = NULL;
11759 rsurface.uselightmaptexture = false;
11760 rsurface.texture = NULL;
11761 rsurface.rtlight = NULL;
11762 numsurfacelist = 0;
11763 // add visible surfaces to draw list
11764 for (i = 0;i < model->nummodelsurfaces;i++)
11765 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11766 // don't do anything if there were no surfaces
11767 if (!numsurfacelist)
11769 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11772 // update lightmaps if needed
11776 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11781 R_BuildLightMap(ent, surfaces + j);
11786 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11788 R_BuildLightMap(ent, surfaces + j);
11789 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11791 // add to stats if desired
11792 if (r_speeds.integer && !skysurfaces && !depthonly)
11794 r_refdef.stats.entities_surfaces += numsurfacelist;
11795 for (j = 0;j < numsurfacelist;j++)
11796 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11799 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11802 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11804 static texture_t texture;
11805 static msurface_t surface;
11806 const msurface_t *surfacelist = &surface;
11808 // fake enough texture and surface state to render this geometry
11810 texture.update_lastrenderframe = -1; // regenerate this texture
11811 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11812 texture.currentskinframe = skinframe;
11813 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11814 texture.offsetmapping = OFFSETMAPPING_OFF;
11815 texture.offsetscale = 1;
11816 texture.specularscalemod = 1;
11817 texture.specularpowermod = 1;
11819 surface.texture = &texture;
11820 surface.num_triangles = numtriangles;
11821 surface.num_firsttriangle = firsttriangle;
11822 surface.num_vertices = numvertices;
11823 surface.num_firstvertex = firstvertex;
11826 rsurface.texture = R_GetCurrentTexture(surface.texture);
11827 rsurface.lightmaptexture = NULL;
11828 rsurface.deluxemaptexture = NULL;
11829 rsurface.uselightmaptexture = false;
11830 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11833 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)
11835 static msurface_t surface;
11836 const msurface_t *surfacelist = &surface;
11838 // fake enough texture and surface state to render this geometry
11839 surface.texture = texture;
11840 surface.num_triangles = numtriangles;
11841 surface.num_firsttriangle = firsttriangle;
11842 surface.num_vertices = numvertices;
11843 surface.num_firstvertex = firstvertex;
11846 rsurface.texture = R_GetCurrentTexture(surface.texture);
11847 rsurface.lightmaptexture = NULL;
11848 rsurface.deluxemaptexture = NULL;
11849 rsurface.uselightmaptexture = false;
11850 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);