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"};
185 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
187 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
188 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
189 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
190 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
192 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
193 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
194 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
195 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
196 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
197 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
198 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
200 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
201 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
202 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
203 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)"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 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_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
213 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"};
215 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"};
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 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"};
224 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."};
226 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)"};
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
231 extern qboolean v_flipped_state;
233 static struct r_bloomstate_s
238 int bloomwidth, bloomheight;
240 textype_t texturetype;
241 int viewfbo; // used to check if r_viewfbo cvar has changed
243 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
244 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
245 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
247 int screentexturewidth, screentextureheight;
248 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
250 int bloomtexturewidth, bloomtextureheight;
251 rtexture_t *texture_bloom;
253 // arrays for rendering the screen passes
254 float screentexcoord2f[8];
255 float bloomtexcoord2f[8];
256 float offsettexcoord2f[8];
258 r_viewport_t viewport;
262 r_waterstate_t r_waterstate;
264 /// shadow volume bsp struct with automatically growing nodes buffer
267 rtexture_t *r_texture_blanknormalmap;
268 rtexture_t *r_texture_white;
269 rtexture_t *r_texture_grey128;
270 rtexture_t *r_texture_black;
271 rtexture_t *r_texture_notexture;
272 rtexture_t *r_texture_whitecube;
273 rtexture_t *r_texture_normalizationcube;
274 rtexture_t *r_texture_fogattenuation;
275 rtexture_t *r_texture_fogheighttexture;
276 rtexture_t *r_texture_gammaramps;
277 unsigned int r_texture_gammaramps_serial;
278 //rtexture_t *r_texture_fogintensity;
279 rtexture_t *r_texture_reflectcube;
281 // TODO: hash lookups?
282 typedef struct cubemapinfo_s
289 int r_texture_numcubemaps;
290 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
292 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
293 unsigned int r_numqueries;
294 unsigned int r_maxqueries;
296 typedef struct r_qwskincache_s
298 char name[MAX_QPATH];
299 skinframe_t *skinframe;
303 static r_qwskincache_t *r_qwskincache;
304 static int r_qwskincache_size;
306 /// vertex coordinates for a quad that covers the screen exactly
307 extern const float r_screenvertex3f[12];
308 extern const float r_d3dscreenvertex3f[12];
309 const float r_screenvertex3f[12] =
316 const float r_d3dscreenvertex3f[12] =
324 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
327 for (i = 0;i < verts;i++)
338 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
341 for (i = 0;i < verts;i++)
351 // FIXME: move this to client?
354 if (gamemode == GAME_NEHAHRA)
356 Cvar_Set("gl_fogenable", "0");
357 Cvar_Set("gl_fogdensity", "0.2");
358 Cvar_Set("gl_fogred", "0.3");
359 Cvar_Set("gl_foggreen", "0.3");
360 Cvar_Set("gl_fogblue", "0.3");
362 r_refdef.fog_density = 0;
363 r_refdef.fog_red = 0;
364 r_refdef.fog_green = 0;
365 r_refdef.fog_blue = 0;
366 r_refdef.fog_alpha = 1;
367 r_refdef.fog_start = 0;
368 r_refdef.fog_end = 16384;
369 r_refdef.fog_height = 1<<30;
370 r_refdef.fog_fadedepth = 128;
371 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
374 static void R_BuildBlankTextures(void)
376 unsigned char data[4];
377 data[2] = 128; // normal X
378 data[1] = 128; // normal Y
379 data[0] = 255; // normal Z
380 data[3] = 255; // height
381 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
399 static void R_BuildNoTexture(void)
402 unsigned char pix[16][16][4];
403 // this makes a light grey/dark grey checkerboard texture
404 for (y = 0;y < 16;y++)
406 for (x = 0;x < 16;x++)
408 if ((y < 8) ^ (x < 8))
424 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
427 static void R_BuildWhiteCube(void)
429 unsigned char data[6*1*1*4];
430 memset(data, 255, sizeof(data));
431 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
434 static void R_BuildNormalizationCube(void)
438 vec_t s, t, intensity;
441 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
442 for (side = 0;side < 6;side++)
444 for (y = 0;y < NORMSIZE;y++)
446 for (x = 0;x < NORMSIZE;x++)
448 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
484 intensity = 127.0f / sqrt(DotProduct(v, v));
485 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
486 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
487 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
488 data[((side*64+y)*64+x)*4+3] = 255;
492 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
496 static void R_BuildFogTexture(void)
500 unsigned char data1[FOGWIDTH][4];
501 //unsigned char data2[FOGWIDTH][4];
504 r_refdef.fogmasktable_start = r_refdef.fog_start;
505 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
506 r_refdef.fogmasktable_range = r_refdef.fogrange;
507 r_refdef.fogmasktable_density = r_refdef.fog_density;
509 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
510 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
512 d = (x * r - r_refdef.fogmasktable_start);
513 if(developer_extra.integer)
514 Con_DPrintf("%f ", d);
516 if (r_fog_exp2.integer)
517 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
519 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
520 if(developer_extra.integer)
521 Con_DPrintf(" : %f ", alpha);
522 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
523 if(developer_extra.integer)
524 Con_DPrintf(" = %f\n", alpha);
525 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
528 for (x = 0;x < FOGWIDTH;x++)
530 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
535 //data2[x][0] = 255 - b;
536 //data2[x][1] = 255 - b;
537 //data2[x][2] = 255 - b;
540 if (r_texture_fogattenuation)
542 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
547 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
548 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
552 static void R_BuildFogHeightTexture(void)
554 unsigned char *inpixels;
562 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
563 if (r_refdef.fogheighttexturename[0])
564 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
567 r_refdef.fog_height_tablesize = 0;
568 if (r_texture_fogheighttexture)
569 R_FreeTexture(r_texture_fogheighttexture);
570 r_texture_fogheighttexture = NULL;
571 if (r_refdef.fog_height_table2d)
572 Mem_Free(r_refdef.fog_height_table2d);
573 r_refdef.fog_height_table2d = NULL;
574 if (r_refdef.fog_height_table1d)
575 Mem_Free(r_refdef.fog_height_table1d);
576 r_refdef.fog_height_table1d = NULL;
580 r_refdef.fog_height_tablesize = size;
581 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
582 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
583 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
585 // LordHavoc: now the magic - what is that table2d for? it is a cooked
586 // average fog color table accounting for every fog layer between a point
587 // and the camera. (Note: attenuation is handled separately!)
588 for (y = 0;y < size;y++)
590 for (x = 0;x < size;x++)
596 for (j = x;j <= y;j++)
598 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604 for (j = x;j >= y;j--)
606 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
611 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
612 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
613 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
614 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
617 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
620 //=======================================================================================================================================================
622 static const char *builtinshaderstring =
623 #include "shader_glsl.h"
626 const char *builtinhlslshaderstring =
627 #include "shader_hlsl.h"
630 char *glslshaderstring = NULL;
631 char *hlslshaderstring = NULL;
633 //=======================================================================================================================================================
635 typedef struct shaderpermutationinfo_s
640 shaderpermutationinfo_t;
642 typedef struct shadermodeinfo_s
644 const char *vertexfilename;
645 const char *geometryfilename;
646 const char *fragmentfilename;
652 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
653 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
655 {"#define USEDIFFUSE\n", " diffuse"},
656 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
657 {"#define USEVIEWTINT\n", " viewtint"},
658 {"#define USECOLORMAPPING\n", " colormapping"},
659 {"#define USESATURATION\n", " saturation"},
660 {"#define USEFOGINSIDE\n", " foginside"},
661 {"#define USEFOGOUTSIDE\n", " fogoutside"},
662 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
663 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
664 {"#define USEGAMMARAMPS\n", " gammaramps"},
665 {"#define USECUBEFILTER\n", " cubefilter"},
666 {"#define USEGLOW\n", " glow"},
667 {"#define USEBLOOM\n", " bloom"},
668 {"#define USESPECULAR\n", " specular"},
669 {"#define USEPOSTPROCESSING\n", " postprocessing"},
670 {"#define USEREFLECTION\n", " reflection"},
671 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
672 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
673 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
674 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
675 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
676 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
677 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
678 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
679 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
680 {"#define USEALPHAKILL\n", " alphakill"},
681 {"#define USEREFLECTCUBE\n", " reflectcube"},
682 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
683 {"#define USEBOUNCEGRID\n", " bouncegrid"},
684 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
685 {"#define USETRIPPY\n", " trippy"},
688 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
689 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
707 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
708 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
711 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
727 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
728 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
729 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
730 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
733 struct r_glsl_permutation_s;
734 typedef struct r_glsl_permutation_s
737 struct r_glsl_permutation_s *hashnext;
739 unsigned int permutation;
741 /// indicates if we have tried compiling this permutation already
743 /// 0 if compilation failed
745 // texture units assigned to each detected uniform
746 int tex_Texture_First;
747 int tex_Texture_Second;
748 int tex_Texture_GammaRamps;
749 int tex_Texture_Normal;
750 int tex_Texture_Color;
751 int tex_Texture_Gloss;
752 int tex_Texture_Glow;
753 int tex_Texture_SecondaryNormal;
754 int tex_Texture_SecondaryColor;
755 int tex_Texture_SecondaryGloss;
756 int tex_Texture_SecondaryGlow;
757 int tex_Texture_Pants;
758 int tex_Texture_Shirt;
759 int tex_Texture_FogHeightTexture;
760 int tex_Texture_FogMask;
761 int tex_Texture_Lightmap;
762 int tex_Texture_Deluxemap;
763 int tex_Texture_Attenuation;
764 int tex_Texture_Cube;
765 int tex_Texture_Refraction;
766 int tex_Texture_Reflection;
767 int tex_Texture_ShadowMap2D;
768 int tex_Texture_CubeProjection;
769 int tex_Texture_ScreenDepth;
770 int tex_Texture_ScreenNormalMap;
771 int tex_Texture_ScreenDiffuse;
772 int tex_Texture_ScreenSpecular;
773 int tex_Texture_ReflectMask;
774 int tex_Texture_ReflectCube;
775 int tex_Texture_BounceGrid;
776 /// locations of detected uniforms in program object, or -1 if not found
777 int loc_Texture_First;
778 int loc_Texture_Second;
779 int loc_Texture_GammaRamps;
780 int loc_Texture_Normal;
781 int loc_Texture_Color;
782 int loc_Texture_Gloss;
783 int loc_Texture_Glow;
784 int loc_Texture_SecondaryNormal;
785 int loc_Texture_SecondaryColor;
786 int loc_Texture_SecondaryGloss;
787 int loc_Texture_SecondaryGlow;
788 int loc_Texture_Pants;
789 int loc_Texture_Shirt;
790 int loc_Texture_FogHeightTexture;
791 int loc_Texture_FogMask;
792 int loc_Texture_Lightmap;
793 int loc_Texture_Deluxemap;
794 int loc_Texture_Attenuation;
795 int loc_Texture_Cube;
796 int loc_Texture_Refraction;
797 int loc_Texture_Reflection;
798 int loc_Texture_ShadowMap2D;
799 int loc_Texture_CubeProjection;
800 int loc_Texture_ScreenDepth;
801 int loc_Texture_ScreenNormalMap;
802 int loc_Texture_ScreenDiffuse;
803 int loc_Texture_ScreenSpecular;
804 int loc_Texture_ReflectMask;
805 int loc_Texture_ReflectCube;
806 int loc_Texture_BounceGrid;
808 int loc_BloomBlur_Parameters;
810 int loc_Color_Ambient;
811 int loc_Color_Diffuse;
812 int loc_Color_Specular;
816 int loc_DeferredColor_Ambient;
817 int loc_DeferredColor_Diffuse;
818 int loc_DeferredColor_Specular;
819 int loc_DeferredMod_Diffuse;
820 int loc_DeferredMod_Specular;
821 int loc_DistortScaleRefractReflect;
824 int loc_FogHeightFade;
826 int loc_FogPlaneViewDist;
827 int loc_FogRangeRecip;
830 int loc_LightPosition;
831 int loc_OffsetMapping_ScaleSteps;
832 int loc_OffsetMapping_LodDistance;
833 int loc_OffsetMapping_Bias;
835 int loc_ReflectColor;
836 int loc_ReflectFactor;
837 int loc_ReflectOffset;
838 int loc_RefractColor;
840 int loc_ScreenCenterRefractReflect;
841 int loc_ScreenScaleRefractReflect;
842 int loc_ScreenToDepth;
843 int loc_ShadowMap_Parameters;
844 int loc_ShadowMap_TextureScale;
845 int loc_SpecularPower;
850 int loc_ViewTintColor;
852 int loc_ModelToLight;
854 int loc_BackgroundTexMatrix;
855 int loc_ModelViewProjectionMatrix;
856 int loc_ModelViewMatrix;
857 int loc_PixelToScreenTexCoord;
858 int loc_ModelToReflectCube;
859 int loc_ShadowMapMatrix;
860 int loc_BloomColorSubtract;
861 int loc_NormalmapScrollBlend;
862 int loc_BounceGridMatrix;
863 int loc_BounceGridIntensity;
865 r_glsl_permutation_t;
867 #define SHADERPERMUTATION_HASHSIZE 256
870 // non-degradable "lightweight" shader parameters to keep the permutations simpler
871 // these can NOT degrade! only use for simple stuff
874 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
875 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
876 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
877 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
878 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
879 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
880 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
881 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
883 #define SHADERSTATICPARMS_COUNT 8
885 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
886 static int shaderstaticparms_count = 0;
888 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
889 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
890 qboolean R_CompileShader_CheckStaticParms(void)
892 static int r_compileshader_staticparms_save[1];
893 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
894 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
897 if (r_glsl_saturation_redcompensate.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
899 if (r_glsl_vertextextureblend_usebothalphas.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
901 if (r_shadow_glossexact.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
903 if (r_glsl_postprocess.integer)
905 if (r_glsl_postprocess_uservec1_enable.integer)
906 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
907 if (r_glsl_postprocess_uservec2_enable.integer)
908 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
909 if (r_glsl_postprocess_uservec3_enable.integer)
910 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
911 if (r_glsl_postprocess_uservec4_enable.integer)
912 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
914 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
916 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
919 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
920 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
921 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
923 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
924 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
926 shaderstaticparms_count = 0;
929 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
930 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
931 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
932 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
933 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
934 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
935 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
936 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939 /// information about each possible shader permutation
940 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
941 /// currently selected permutation
942 r_glsl_permutation_t *r_glsl_permutation;
943 /// storage for permutations linked in the hash table
944 memexpandablearray_t r_glsl_permutationarray;
946 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
948 //unsigned int hashdepth = 0;
949 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
950 r_glsl_permutation_t *p;
951 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
953 if (p->mode == mode && p->permutation == permutation)
955 //if (hashdepth > 10)
956 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
961 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
963 p->permutation = permutation;
964 p->hashnext = r_glsl_permutationhash[mode][hashindex];
965 r_glsl_permutationhash[mode][hashindex] = p;
966 //if (hashdepth > 10)
967 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
971 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
974 if (!filename || !filename[0])
976 if (!strcmp(filename, "glsl/default.glsl"))
978 if (!glslshaderstring)
980 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
981 if (glslshaderstring)
982 Con_DPrintf("Loading shaders from file %s...\n", filename);
984 glslshaderstring = (char *)builtinshaderstring;
986 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
987 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
990 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
993 if (printfromdisknotice)
994 Con_DPrintf("from disk %s... ", filename);
1000 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1004 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1005 char *vertexstring, *geometrystring, *fragmentstring;
1006 char permutationname[256];
1007 int vertstrings_count = 0;
1008 int geomstrings_count = 0;
1009 int fragstrings_count = 0;
1010 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1011 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1012 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1019 permutationname[0] = 0;
1020 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1021 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1022 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1024 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1026 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1027 if(vid.support.gl20shaders130)
1029 vertstrings_list[vertstrings_count++] = "#version 130\n";
1030 geomstrings_list[geomstrings_count++] = "#version 130\n";
1031 fragstrings_list[fragstrings_count++] = "#version 130\n";
1032 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1033 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1034 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1037 // the first pretext is which type of shader to compile as
1038 // (later these will all be bound together as a program object)
1039 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1040 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1041 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1043 // the second pretext is the mode (for example a light source)
1044 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1045 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1046 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1047 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1049 // now add all the permutation pretexts
1050 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1052 if (permutation & (1<<i))
1054 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1055 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1056 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1057 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1061 // keep line numbers correct
1062 vertstrings_list[vertstrings_count++] = "\n";
1063 geomstrings_list[geomstrings_count++] = "\n";
1064 fragstrings_list[fragstrings_count++] = "\n";
1069 R_CompileShader_AddStaticParms(mode, permutation);
1070 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071 vertstrings_count += shaderstaticparms_count;
1072 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073 geomstrings_count += shaderstaticparms_count;
1074 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1075 fragstrings_count += shaderstaticparms_count;
1077 // now append the shader text itself
1078 vertstrings_list[vertstrings_count++] = vertexstring;
1079 geomstrings_list[geomstrings_count++] = geometrystring;
1080 fragstrings_list[fragstrings_count++] = fragmentstring;
1082 // if any sources were NULL, clear the respective list
1084 vertstrings_count = 0;
1085 if (!geometrystring)
1086 geomstrings_count = 0;
1087 if (!fragmentstring)
1088 fragstrings_count = 0;
1090 // compile the shader program
1091 if (vertstrings_count + geomstrings_count + fragstrings_count)
1092 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1096 qglUseProgram(p->program);CHECKGLERROR
1097 // look up all the uniform variable names we care about, so we don't
1098 // have to look them up every time we set them
1100 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1101 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1102 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1103 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1104 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1105 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1106 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1107 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1108 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1109 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1110 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1111 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1112 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1113 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1114 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1115 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1116 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1117 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1118 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1119 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1120 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1121 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1122 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1123 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1124 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1125 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1126 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1127 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1128 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1129 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1130 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1131 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1132 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1133 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1134 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1135 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1136 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1137 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1138 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1139 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1140 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1141 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1142 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1143 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1144 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1145 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1146 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1147 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1148 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1149 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1150 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1151 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1152 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1153 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1154 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1155 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1156 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1157 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1158 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1159 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1160 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1161 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1162 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1163 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1164 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1165 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1166 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1167 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1168 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1169 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1170 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1171 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1172 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1173 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1174 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1175 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1176 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1177 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1178 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1179 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1180 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1181 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1182 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1183 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1184 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1185 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1186 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1187 // initialize the samplers to refer to the texture units we use
1188 p->tex_Texture_First = -1;
1189 p->tex_Texture_Second = -1;
1190 p->tex_Texture_GammaRamps = -1;
1191 p->tex_Texture_Normal = -1;
1192 p->tex_Texture_Color = -1;
1193 p->tex_Texture_Gloss = -1;
1194 p->tex_Texture_Glow = -1;
1195 p->tex_Texture_SecondaryNormal = -1;
1196 p->tex_Texture_SecondaryColor = -1;
1197 p->tex_Texture_SecondaryGloss = -1;
1198 p->tex_Texture_SecondaryGlow = -1;
1199 p->tex_Texture_Pants = -1;
1200 p->tex_Texture_Shirt = -1;
1201 p->tex_Texture_FogHeightTexture = -1;
1202 p->tex_Texture_FogMask = -1;
1203 p->tex_Texture_Lightmap = -1;
1204 p->tex_Texture_Deluxemap = -1;
1205 p->tex_Texture_Attenuation = -1;
1206 p->tex_Texture_Cube = -1;
1207 p->tex_Texture_Refraction = -1;
1208 p->tex_Texture_Reflection = -1;
1209 p->tex_Texture_ShadowMap2D = -1;
1210 p->tex_Texture_CubeProjection = -1;
1211 p->tex_Texture_ScreenDepth = -1;
1212 p->tex_Texture_ScreenNormalMap = -1;
1213 p->tex_Texture_ScreenDiffuse = -1;
1214 p->tex_Texture_ScreenSpecular = -1;
1215 p->tex_Texture_ReflectMask = -1;
1216 p->tex_Texture_ReflectCube = -1;
1217 p->tex_Texture_BounceGrid = -1;
1219 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1220 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1221 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1222 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1223 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1224 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1225 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1226 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1227 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1228 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1229 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1230 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1231 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1232 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1233 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1234 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1235 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1236 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1237 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1238 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1239 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1240 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1241 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1242 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1243 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1244 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1245 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1246 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1247 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1248 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1250 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1253 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1257 Mem_Free(vertexstring);
1259 Mem_Free(geometrystring);
1261 Mem_Free(fragmentstring);
1264 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1266 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1267 if (r_glsl_permutation != perm)
1269 r_glsl_permutation = perm;
1270 if (!r_glsl_permutation->program)
1272 if (!r_glsl_permutation->compiled)
1273 R_GLSL_CompilePermutation(perm, mode, permutation);
1274 if (!r_glsl_permutation->program)
1276 // remove features until we find a valid permutation
1278 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1280 // reduce i more quickly whenever it would not remove any bits
1281 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1282 if (!(permutation & j))
1285 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1286 if (!r_glsl_permutation->compiled)
1287 R_GLSL_CompilePermutation(perm, mode, permutation);
1288 if (r_glsl_permutation->program)
1291 if (i >= SHADERPERMUTATION_COUNT)
1293 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1294 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1295 qglUseProgram(0);CHECKGLERROR
1296 return; // no bit left to clear, entire mode is broken
1301 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1303 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1304 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1305 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1312 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1313 extern D3DCAPS9 vid_d3d9caps;
1316 struct r_hlsl_permutation_s;
1317 typedef struct r_hlsl_permutation_s
1319 /// hash lookup data
1320 struct r_hlsl_permutation_s *hashnext;
1322 unsigned int permutation;
1324 /// indicates if we have tried compiling this permutation already
1326 /// NULL if compilation failed
1327 IDirect3DVertexShader9 *vertexshader;
1328 IDirect3DPixelShader9 *pixelshader;
1330 r_hlsl_permutation_t;
1332 typedef enum D3DVSREGISTER_e
1334 D3DVSREGISTER_TexMatrix = 0, // float4x4
1335 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1336 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1337 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1338 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1339 D3DVSREGISTER_ModelToLight = 20, // float4x4
1340 D3DVSREGISTER_EyePosition = 24,
1341 D3DVSREGISTER_FogPlane = 25,
1342 D3DVSREGISTER_LightDir = 26,
1343 D3DVSREGISTER_LightPosition = 27,
1347 typedef enum D3DPSREGISTER_e
1349 D3DPSREGISTER_Alpha = 0,
1350 D3DPSREGISTER_BloomBlur_Parameters = 1,
1351 D3DPSREGISTER_ClientTime = 2,
1352 D3DPSREGISTER_Color_Ambient = 3,
1353 D3DPSREGISTER_Color_Diffuse = 4,
1354 D3DPSREGISTER_Color_Specular = 5,
1355 D3DPSREGISTER_Color_Glow = 6,
1356 D3DPSREGISTER_Color_Pants = 7,
1357 D3DPSREGISTER_Color_Shirt = 8,
1358 D3DPSREGISTER_DeferredColor_Ambient = 9,
1359 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1360 D3DPSREGISTER_DeferredColor_Specular = 11,
1361 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1362 D3DPSREGISTER_DeferredMod_Specular = 13,
1363 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1364 D3DPSREGISTER_EyePosition = 15, // unused
1365 D3DPSREGISTER_FogColor = 16,
1366 D3DPSREGISTER_FogHeightFade = 17,
1367 D3DPSREGISTER_FogPlane = 18,
1368 D3DPSREGISTER_FogPlaneViewDist = 19,
1369 D3DPSREGISTER_FogRangeRecip = 20,
1370 D3DPSREGISTER_LightColor = 21,
1371 D3DPSREGISTER_LightDir = 22, // unused
1372 D3DPSREGISTER_LightPosition = 23,
1373 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1374 D3DPSREGISTER_PixelSize = 25,
1375 D3DPSREGISTER_ReflectColor = 26,
1376 D3DPSREGISTER_ReflectFactor = 27,
1377 D3DPSREGISTER_ReflectOffset = 28,
1378 D3DPSREGISTER_RefractColor = 29,
1379 D3DPSREGISTER_Saturation = 30,
1380 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1381 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1382 D3DPSREGISTER_ScreenToDepth = 33,
1383 D3DPSREGISTER_ShadowMap_Parameters = 34,
1384 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1385 D3DPSREGISTER_SpecularPower = 36,
1386 D3DPSREGISTER_UserVec1 = 37,
1387 D3DPSREGISTER_UserVec2 = 38,
1388 D3DPSREGISTER_UserVec3 = 39,
1389 D3DPSREGISTER_UserVec4 = 40,
1390 D3DPSREGISTER_ViewTintColor = 41,
1391 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1392 D3DPSREGISTER_BloomColorSubtract = 43,
1393 D3DPSREGISTER_ViewToLight = 44, // float4x4
1394 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1395 D3DPSREGISTER_NormalmapScrollBlend = 52,
1396 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1397 D3DPSREGISTER_OffsetMapping_Bias = 54,
1402 /// information about each possible shader permutation
1403 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1404 /// currently selected permutation
1405 r_hlsl_permutation_t *r_hlsl_permutation;
1406 /// storage for permutations linked in the hash table
1407 memexpandablearray_t r_hlsl_permutationarray;
1409 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1411 //unsigned int hashdepth = 0;
1412 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1413 r_hlsl_permutation_t *p;
1414 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1416 if (p->mode == mode && p->permutation == permutation)
1418 //if (hashdepth > 10)
1419 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1424 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1426 p->permutation = permutation;
1427 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1428 r_hlsl_permutationhash[mode][hashindex] = p;
1429 //if (hashdepth > 10)
1430 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1434 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1437 if (!filename || !filename[0])
1439 if (!strcmp(filename, "hlsl/default.hlsl"))
1441 if (!hlslshaderstring)
1443 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1444 if (hlslshaderstring)
1445 Con_DPrintf("Loading shaders from file %s...\n", filename);
1447 hlslshaderstring = (char *)builtinhlslshaderstring;
1449 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1450 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1451 return shaderstring;
1453 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1456 if (printfromdisknotice)
1457 Con_DPrintf("from disk %s... ", filename);
1458 return shaderstring;
1460 return shaderstring;
1464 //#include <d3dx9shader.h>
1465 //#include <d3dx9mesh.h>
1467 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1469 DWORD *vsbin = NULL;
1470 DWORD *psbin = NULL;
1471 fs_offset_t vsbinsize;
1472 fs_offset_t psbinsize;
1473 // IDirect3DVertexShader9 *vs = NULL;
1474 // IDirect3DPixelShader9 *ps = NULL;
1475 ID3DXBuffer *vslog = NULL;
1476 ID3DXBuffer *vsbuffer = NULL;
1477 ID3DXConstantTable *vsconstanttable = NULL;
1478 ID3DXBuffer *pslog = NULL;
1479 ID3DXBuffer *psbuffer = NULL;
1480 ID3DXConstantTable *psconstanttable = NULL;
1483 char temp[MAX_INPUTLINE];
1484 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1485 qboolean debugshader = gl_paranoid.integer != 0;
1486 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1487 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1490 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1491 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1493 if ((!vsbin && vertstring) || (!psbin && fragstring))
1495 const char* dllnames_d3dx9 [] =
1519 dllhandle_t d3dx9_dll = NULL;
1520 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1521 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1522 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1523 dllfunction_t d3dx9_dllfuncs[] =
1525 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1526 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1527 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1530 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1532 DWORD shaderflags = 0;
1534 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1535 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1536 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1537 if (vertstring && vertstring[0])
1541 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1542 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1543 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1544 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1547 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1550 vsbinsize = vsbuffer->GetBufferSize();
1551 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1552 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1553 vsbuffer->Release();
1557 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1558 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1562 if (fragstring && fragstring[0])
1566 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1567 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1568 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1569 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1575 psbinsize = psbuffer->GetBufferSize();
1576 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1577 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1578 psbuffer->Release();
1582 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1583 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1587 Sys_UnloadLibrary(&d3dx9_dll);
1590 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1594 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1595 if (FAILED(vsresult))
1596 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1597 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1598 if (FAILED(psresult))
1599 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1601 // free the shader data
1602 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1603 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1606 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1609 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1610 int vertstring_length = 0;
1611 int geomstring_length = 0;
1612 int fragstring_length = 0;
1614 char *vertexstring, *geometrystring, *fragmentstring;
1615 char *vertstring, *geomstring, *fragstring;
1616 char permutationname[256];
1617 char cachename[256];
1618 int vertstrings_count = 0;
1619 int geomstrings_count = 0;
1620 int fragstrings_count = 0;
1621 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1622 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1623 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1628 p->vertexshader = NULL;
1629 p->pixelshader = NULL;
1631 permutationname[0] = 0;
1633 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1634 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1635 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1637 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1638 strlcat(cachename, "hlsl/", sizeof(cachename));
1640 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1641 vertstrings_count = 0;
1642 geomstrings_count = 0;
1643 fragstrings_count = 0;
1644 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1645 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1646 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1648 // the first pretext is which type of shader to compile as
1649 // (later these will all be bound together as a program object)
1650 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1651 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1652 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1654 // the second pretext is the mode (for example a light source)
1655 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1656 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1657 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1658 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1659 strlcat(cachename, modeinfo->name, sizeof(cachename));
1661 // now add all the permutation pretexts
1662 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1664 if (permutation & (1<<i))
1666 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1667 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1668 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1669 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1670 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1674 // keep line numbers correct
1675 vertstrings_list[vertstrings_count++] = "\n";
1676 geomstrings_list[geomstrings_count++] = "\n";
1677 fragstrings_list[fragstrings_count++] = "\n";
1682 R_CompileShader_AddStaticParms(mode, permutation);
1683 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684 vertstrings_count += shaderstaticparms_count;
1685 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686 geomstrings_count += shaderstaticparms_count;
1687 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688 fragstrings_count += shaderstaticparms_count;
1690 // replace spaces in the cachename with _ characters
1691 for (i = 0;cachename[i];i++)
1692 if (cachename[i] == ' ')
1695 // now append the shader text itself
1696 vertstrings_list[vertstrings_count++] = vertexstring;
1697 geomstrings_list[geomstrings_count++] = geometrystring;
1698 fragstrings_list[fragstrings_count++] = fragmentstring;
1700 // if any sources were NULL, clear the respective list
1702 vertstrings_count = 0;
1703 if (!geometrystring)
1704 geomstrings_count = 0;
1705 if (!fragmentstring)
1706 fragstrings_count = 0;
1708 vertstring_length = 0;
1709 for (i = 0;i < vertstrings_count;i++)
1710 vertstring_length += strlen(vertstrings_list[i]);
1711 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1712 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1713 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1715 geomstring_length = 0;
1716 for (i = 0;i < geomstrings_count;i++)
1717 geomstring_length += strlen(geomstrings_list[i]);
1718 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1719 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1720 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1722 fragstring_length = 0;
1723 for (i = 0;i < fragstrings_count;i++)
1724 fragstring_length += strlen(fragstrings_list[i]);
1725 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1726 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1727 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1729 // try to load the cached shader, or generate one
1730 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1732 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1733 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1735 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1739 Mem_Free(vertstring);
1741 Mem_Free(geomstring);
1743 Mem_Free(fragstring);
1745 Mem_Free(vertexstring);
1747 Mem_Free(geometrystring);
1749 Mem_Free(fragmentstring);
1752 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1753 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1754 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);}
1755 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);}
1756 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);}
1757 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);}
1759 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1760 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1761 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);}
1762 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);}
1763 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);}
1764 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);}
1766 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1768 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1769 if (r_hlsl_permutation != perm)
1771 r_hlsl_permutation = perm;
1772 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774 if (!r_hlsl_permutation->compiled)
1775 R_HLSL_CompilePermutation(perm, mode, permutation);
1776 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1778 // remove features until we find a valid permutation
1780 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1782 // reduce i more quickly whenever it would not remove any bits
1783 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1784 if (!(permutation & j))
1787 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1788 if (!r_hlsl_permutation->compiled)
1789 R_HLSL_CompilePermutation(perm, mode, permutation);
1790 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1793 if (i >= SHADERPERMUTATION_COUNT)
1795 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1796 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1797 return; // no bit left to clear, entire mode is broken
1801 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1802 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1804 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1805 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1806 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1810 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1812 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1813 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1814 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1815 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1818 void R_GLSL_Restart_f(void)
1820 unsigned int i, limit;
1821 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1822 Mem_Free(glslshaderstring);
1823 glslshaderstring = NULL;
1824 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1825 Mem_Free(hlslshaderstring);
1826 hlslshaderstring = NULL;
1827 switch(vid.renderpath)
1829 case RENDERPATH_D3D9:
1832 r_hlsl_permutation_t *p;
1833 r_hlsl_permutation = NULL;
1834 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1835 for (i = 0;i < limit;i++)
1837 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1839 if (p->vertexshader)
1840 IDirect3DVertexShader9_Release(p->vertexshader);
1842 IDirect3DPixelShader9_Release(p->pixelshader);
1843 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1846 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1850 case RENDERPATH_D3D10:
1851 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853 case RENDERPATH_D3D11:
1854 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1856 case RENDERPATH_GL20:
1857 case RENDERPATH_GLES2:
1859 r_glsl_permutation_t *p;
1860 r_glsl_permutation = NULL;
1861 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1862 for (i = 0;i < limit;i++)
1864 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1866 GL_Backend_FreeProgram(p->program);
1867 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1870 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1873 case RENDERPATH_GL11:
1874 case RENDERPATH_GL13:
1875 case RENDERPATH_GLES1:
1877 case RENDERPATH_SOFT:
1882 void R_GLSL_DumpShader_f(void)
1887 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1890 FS_Print(file, "/* The engine may define the following macros:\n");
1891 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1892 for (i = 0;i < SHADERMODE_COUNT;i++)
1893 FS_Print(file, glslshadermodeinfo[i].pretext);
1894 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1895 FS_Print(file, shaderpermutationinfo[i].pretext);
1896 FS_Print(file, "*/\n");
1897 FS_Print(file, builtinshaderstring);
1899 Con_Printf("glsl/default.glsl written\n");
1902 Con_Printf("failed to write to glsl/default.glsl\n");
1904 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1907 FS_Print(file, "/* The engine may define the following macros:\n");
1908 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1909 for (i = 0;i < SHADERMODE_COUNT;i++)
1910 FS_Print(file, hlslshadermodeinfo[i].pretext);
1911 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1912 FS_Print(file, shaderpermutationinfo[i].pretext);
1913 FS_Print(file, "*/\n");
1914 FS_Print(file, builtinhlslshaderstring);
1916 Con_Printf("hlsl/default.hlsl written\n");
1919 Con_Printf("failed to write to hlsl/default.hlsl\n");
1922 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1924 unsigned int permutation = 0;
1925 if (r_trippy.integer && !notrippy)
1926 permutation |= SHADERPERMUTATION_TRIPPY;
1927 permutation |= SHADERPERMUTATION_VIEWTINT;
1929 permutation |= SHADERPERMUTATION_DIFFUSE;
1931 permutation |= SHADERPERMUTATION_SPECULAR;
1932 if (texturemode == GL_MODULATE)
1933 permutation |= SHADERPERMUTATION_COLORMAPPING;
1934 else if (texturemode == GL_ADD)
1935 permutation |= SHADERPERMUTATION_GLOW;
1936 else if (texturemode == GL_DECAL)
1937 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1938 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1939 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1941 texturemode = GL_MODULATE;
1942 if (vid.allowalphatocoverage)
1943 GL_AlphaToCoverage(false);
1944 switch (vid.renderpath)
1946 case RENDERPATH_D3D9:
1948 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1949 R_Mesh_TexBind(GL20TU_FIRST , first );
1950 R_Mesh_TexBind(GL20TU_SECOND, second);
1951 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1952 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1955 case RENDERPATH_D3D10:
1956 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958 case RENDERPATH_D3D11:
1959 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_GL20:
1962 case RENDERPATH_GLES2:
1963 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1964 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1965 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1966 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1967 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1969 case RENDERPATH_GL13:
1970 case RENDERPATH_GLES1:
1971 R_Mesh_TexBind(0, first );
1972 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1973 R_Mesh_TexBind(1, second);
1975 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1977 case RENDERPATH_GL11:
1978 R_Mesh_TexBind(0, first );
1980 case RENDERPATH_SOFT:
1981 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1982 R_Mesh_TexBind(GL20TU_FIRST , first );
1983 R_Mesh_TexBind(GL20TU_SECOND, second);
1988 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1990 unsigned int permutation = 0;
1991 if (r_trippy.integer && !notrippy)
1992 permutation |= SHADERPERMUTATION_TRIPPY;
1993 if (vid.allowalphatocoverage)
1994 GL_AlphaToCoverage(false);
1995 switch (vid.renderpath)
1997 case RENDERPATH_D3D9:
1999 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2002 case RENDERPATH_D3D10:
2003 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2005 case RENDERPATH_D3D11:
2006 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2008 case RENDERPATH_GL20:
2009 case RENDERPATH_GLES2:
2010 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2012 case RENDERPATH_GL13:
2013 case RENDERPATH_GLES1:
2014 R_Mesh_TexBind(0, 0);
2015 R_Mesh_TexBind(1, 0);
2017 case RENDERPATH_GL11:
2018 R_Mesh_TexBind(0, 0);
2020 case RENDERPATH_SOFT:
2021 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2026 void R_SetupShader_ShowDepth(qboolean notrippy)
2028 int permutation = 0;
2029 if (r_trippy.integer && !notrippy)
2030 permutation |= SHADERPERMUTATION_TRIPPY;
2031 if (vid.allowalphatocoverage)
2032 GL_AlphaToCoverage(false);
2033 switch (vid.renderpath)
2035 case RENDERPATH_D3D9:
2037 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2040 case RENDERPATH_D3D10:
2041 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043 case RENDERPATH_D3D11:
2044 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2046 case RENDERPATH_GL20:
2047 case RENDERPATH_GLES2:
2048 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2050 case RENDERPATH_GL13:
2051 case RENDERPATH_GLES1:
2053 case RENDERPATH_GL11:
2055 case RENDERPATH_SOFT:
2056 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2061 extern qboolean r_shadow_usingdeferredprepass;
2062 extern cvar_t r_shadow_deferred_8bitrange;
2063 extern rtexture_t *r_shadow_attenuationgradienttexture;
2064 extern rtexture_t *r_shadow_attenuation2dtexture;
2065 extern rtexture_t *r_shadow_attenuation3dtexture;
2066 extern qboolean r_shadow_usingshadowmap2d;
2067 extern qboolean r_shadow_usingshadowmaportho;
2068 extern float r_shadow_shadowmap_texturescale[2];
2069 extern float r_shadow_shadowmap_parameters[4];
2070 extern qboolean r_shadow_shadowmapvsdct;
2071 extern qboolean r_shadow_shadowmapsampler;
2072 extern int r_shadow_shadowmappcf;
2073 extern rtexture_t *r_shadow_shadowmap2dtexture;
2074 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2075 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2076 extern matrix4x4_t r_shadow_shadowmapmatrix;
2077 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2078 extern int r_shadow_prepass_width;
2079 extern int r_shadow_prepass_height;
2080 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2081 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2082 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2083 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2084 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2086 #define BLENDFUNC_ALLOWS_COLORMOD 1
2087 #define BLENDFUNC_ALLOWS_FOG 2
2088 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2089 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2090 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2091 static int R_BlendFuncFlags(int src, int dst)
2095 // a blendfunc allows colormod if:
2096 // a) it can never keep the destination pixel invariant, or
2097 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2098 // this is to prevent unintended side effects from colormod
2100 // a blendfunc allows fog if:
2101 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2102 // this is to prevent unintended side effects from fog
2104 // these checks are the output of fogeval.pl
2106 r |= BLENDFUNC_ALLOWS_COLORMOD;
2107 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2108 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2109 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2111 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2116 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2117 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2118 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2119 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2120 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2121 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2122 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2125 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2126 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2127 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2132 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)
2134 // select a permutation of the lighting shader appropriate to this
2135 // combination of texture, entity, light source, and fogging, only use the
2136 // minimum features necessary to avoid wasting rendering time in the
2137 // fragment shader on features that are not being used
2138 unsigned int permutation = 0;
2139 unsigned int mode = 0;
2141 static float dummy_colormod[3] = {1, 1, 1};
2142 float *colormod = rsurface.colormod;
2144 matrix4x4_t tempmatrix;
2145 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2146 if (r_trippy.integer && !notrippy)
2147 permutation |= SHADERPERMUTATION_TRIPPY;
2148 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2149 permutation |= SHADERPERMUTATION_ALPHAKILL;
2150 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2151 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2152 if (rsurfacepass == RSURFPASS_BACKGROUND)
2154 // distorted background
2155 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2157 mode = SHADERMODE_WATER;
2158 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2160 // this is the right thing to do for wateralpha
2161 GL_BlendFunc(GL_ONE, GL_ZERO);
2162 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2166 // this is the right thing to do for entity alpha
2167 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2168 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2173 mode = SHADERMODE_REFRACTION;
2174 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2175 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2179 mode = SHADERMODE_GENERIC;
2180 permutation |= SHADERPERMUTATION_DIFFUSE;
2181 GL_BlendFunc(GL_ONE, GL_ZERO);
2182 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2184 if (vid.allowalphatocoverage)
2185 GL_AlphaToCoverage(false);
2187 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2189 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2191 switch(rsurface.texture->offsetmapping)
2193 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196 case OFFSETMAPPING_OFF: break;
2199 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201 // normalmap (deferred prepass), may use alpha test on diffuse
2202 mode = SHADERMODE_DEFERREDGEOMETRY;
2203 GL_BlendFunc(GL_ONE, GL_ZERO);
2204 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2205 if (vid.allowalphatocoverage)
2206 GL_AlphaToCoverage(false);
2208 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2210 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2212 switch(rsurface.texture->offsetmapping)
2214 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2215 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2217 case OFFSETMAPPING_OFF: break;
2220 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2221 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2223 mode = SHADERMODE_LIGHTSOURCE;
2224 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2225 permutation |= SHADERPERMUTATION_CUBEFILTER;
2226 if (diffusescale > 0)
2227 permutation |= SHADERPERMUTATION_DIFFUSE;
2228 if (specularscale > 0)
2229 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2230 if (r_refdef.fogenabled)
2231 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2232 if (rsurface.texture->colormapping)
2233 permutation |= SHADERPERMUTATION_COLORMAPPING;
2234 if (r_shadow_usingshadowmap2d)
2236 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2237 if(r_shadow_shadowmapvsdct)
2238 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2240 if (r_shadow_shadowmapsampler)
2241 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2242 if (r_shadow_shadowmappcf > 1)
2243 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2244 else if (r_shadow_shadowmappcf)
2245 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2247 if (rsurface.texture->reflectmasktexture)
2248 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2249 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2250 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2251 if (vid.allowalphatocoverage)
2252 GL_AlphaToCoverage(false);
2254 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2256 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2258 switch(rsurface.texture->offsetmapping)
2260 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2261 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2262 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2263 case OFFSETMAPPING_OFF: break;
2266 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2267 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2268 // unshaded geometry (fullbright or ambient model lighting)
2269 mode = SHADERMODE_FLATCOLOR;
2270 ambientscale = diffusescale = specularscale = 0;
2271 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2272 permutation |= SHADERPERMUTATION_GLOW;
2273 if (r_refdef.fogenabled)
2274 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2275 if (rsurface.texture->colormapping)
2276 permutation |= SHADERPERMUTATION_COLORMAPPING;
2277 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2279 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2280 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2282 if (r_shadow_shadowmapsampler)
2283 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2284 if (r_shadow_shadowmappcf > 1)
2285 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2286 else if (r_shadow_shadowmappcf)
2287 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2289 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2290 permutation |= SHADERPERMUTATION_REFLECTION;
2291 if (rsurface.texture->reflectmasktexture)
2292 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2293 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295 // when using alphatocoverage, we don't need alphakill
2296 if (vid.allowalphatocoverage)
2298 if (r_transparent_alphatocoverage.integer)
2300 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2301 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2304 GL_AlphaToCoverage(false);
2307 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2309 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311 switch(rsurface.texture->offsetmapping)
2313 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316 case OFFSETMAPPING_OFF: break;
2319 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321 // directional model lighting
2322 mode = SHADERMODE_LIGHTDIRECTION;
2323 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2324 permutation |= SHADERPERMUTATION_GLOW;
2325 permutation |= SHADERPERMUTATION_DIFFUSE;
2326 if (specularscale > 0)
2327 permutation |= SHADERPERMUTATION_SPECULAR;
2328 if (r_refdef.fogenabled)
2329 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330 if (rsurface.texture->colormapping)
2331 permutation |= SHADERPERMUTATION_COLORMAPPING;
2332 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2334 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2337 if (r_shadow_shadowmapsampler)
2338 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2339 if (r_shadow_shadowmappcf > 1)
2340 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2341 else if (r_shadow_shadowmappcf)
2342 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2344 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345 permutation |= SHADERPERMUTATION_REFLECTION;
2346 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2347 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2348 if (rsurface.texture->reflectmasktexture)
2349 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2352 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2353 if (r_shadow_bouncegriddirectional)
2354 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2356 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2358 // when using alphatocoverage, we don't need alphakill
2359 if (vid.allowalphatocoverage)
2361 if (r_transparent_alphatocoverage.integer)
2363 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2364 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2367 GL_AlphaToCoverage(false);
2370 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2372 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2374 switch(rsurface.texture->offsetmapping)
2376 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2377 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379 case OFFSETMAPPING_OFF: break;
2382 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2383 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2384 // ambient model lighting
2385 mode = SHADERMODE_LIGHTDIRECTION;
2386 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2387 permutation |= SHADERPERMUTATION_GLOW;
2388 if (r_refdef.fogenabled)
2389 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2390 if (rsurface.texture->colormapping)
2391 permutation |= SHADERPERMUTATION_COLORMAPPING;
2392 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2394 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2395 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2397 if (r_shadow_shadowmapsampler)
2398 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2399 if (r_shadow_shadowmappcf > 1)
2400 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2401 else if (r_shadow_shadowmappcf)
2402 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2405 permutation |= SHADERPERMUTATION_REFLECTION;
2406 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2407 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2408 if (rsurface.texture->reflectmasktexture)
2409 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2410 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2412 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2413 if (r_shadow_bouncegriddirectional)
2414 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2416 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2418 // when using alphatocoverage, we don't need alphakill
2419 if (vid.allowalphatocoverage)
2421 if (r_transparent_alphatocoverage.integer)
2423 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2424 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2427 GL_AlphaToCoverage(false);
2432 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2434 switch(rsurface.texture->offsetmapping)
2436 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2437 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2438 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2439 case OFFSETMAPPING_OFF: break;
2442 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2443 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2445 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446 permutation |= SHADERPERMUTATION_GLOW;
2447 if (r_refdef.fogenabled)
2448 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449 if (rsurface.texture->colormapping)
2450 permutation |= SHADERPERMUTATION_COLORMAPPING;
2451 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2453 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2456 if (r_shadow_shadowmapsampler)
2457 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2458 if (r_shadow_shadowmappcf > 1)
2459 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2460 else if (r_shadow_shadowmappcf)
2461 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2463 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2464 permutation |= SHADERPERMUTATION_REFLECTION;
2465 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2466 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2467 if (rsurface.texture->reflectmasktexture)
2468 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2469 if (FAKELIGHT_ENABLED)
2471 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2472 mode = SHADERMODE_FAKELIGHT;
2473 permutation |= SHADERPERMUTATION_DIFFUSE;
2474 if (specularscale > 0)
2475 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2477 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2479 // deluxemapping (light direction texture)
2480 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2481 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2483 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2484 permutation |= SHADERPERMUTATION_DIFFUSE;
2485 if (specularscale > 0)
2486 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2488 else if (r_glsl_deluxemapping.integer >= 2)
2490 // fake deluxemapping (uniform light direction in tangentspace)
2491 if (rsurface.uselightmaptexture)
2492 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2494 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2495 permutation |= SHADERPERMUTATION_DIFFUSE;
2496 if (specularscale > 0)
2497 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2499 else if (rsurface.uselightmaptexture)
2501 // ordinary lightmapping (q1bsp, q3bsp)
2502 mode = SHADERMODE_LIGHTMAP;
2506 // ordinary vertex coloring (q3bsp)
2507 mode = SHADERMODE_VERTEXCOLOR;
2509 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2511 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2512 if (r_shadow_bouncegriddirectional)
2513 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2515 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2516 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2517 // when using alphatocoverage, we don't need alphakill
2518 if (vid.allowalphatocoverage)
2520 if (r_transparent_alphatocoverage.integer)
2522 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2523 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2526 GL_AlphaToCoverage(false);
2529 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2530 colormod = dummy_colormod;
2531 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2532 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2533 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2534 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2535 switch(vid.renderpath)
2537 case RENDERPATH_D3D9:
2539 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);
2540 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2541 R_SetupShader_SetPermutationHLSL(mode, permutation);
2542 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2543 if (mode == SHADERMODE_LIGHTSOURCE)
2545 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2546 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2550 if (mode == SHADERMODE_LIGHTDIRECTION)
2552 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2555 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2556 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2557 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2558 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2559 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2561 if (mode == SHADERMODE_LIGHTSOURCE)
2563 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2564 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2565 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2566 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2567 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2569 // additive passes are only darkened by fog, not tinted
2570 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2571 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2575 if (mode == SHADERMODE_FLATCOLOR)
2577 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2579 else if (mode == SHADERMODE_LIGHTDIRECTION)
2581 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]);
2582 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2583 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);
2584 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);
2585 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2586 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2587 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2591 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2592 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2593 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);
2594 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);
2595 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2597 // additive passes are only darkened by fog, not tinted
2598 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2599 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2601 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2602 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);
2603 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2604 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2605 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2606 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2607 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2608 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2609 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2610 if (mode == SHADERMODE_WATER)
2611 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2613 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2614 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2615 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2616 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));
2617 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2618 if (rsurface.texture->pantstexture)
2619 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2621 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2622 if (rsurface.texture->shirttexture)
2623 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2625 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2626 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2627 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2628 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2629 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2630 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2631 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2632 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2633 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2634 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2636 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2637 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2638 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2639 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2641 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2642 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2643 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2644 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2645 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2646 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2647 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2648 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2649 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2650 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2651 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2652 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2653 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2654 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2655 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2656 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2657 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2658 if (rsurfacepass == RSURFPASS_BACKGROUND)
2660 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2661 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2662 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2666 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2668 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2669 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2670 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2671 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2672 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2674 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2675 if (rsurface.rtlight)
2677 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2678 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2683 case RENDERPATH_D3D10:
2684 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2686 case RENDERPATH_D3D11:
2687 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2689 case RENDERPATH_GL20:
2690 case RENDERPATH_GLES2:
2691 if (!vid.useinterleavedarrays)
2693 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);
2694 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2695 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2696 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2697 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2698 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2699 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2700 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2704 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);
2705 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2707 R_SetupShader_SetPermutationGLSL(mode, permutation);
2708 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2709 if (mode == SHADERMODE_LIGHTSOURCE)
2711 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2712 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2713 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2714 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2715 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2716 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);
2718 // additive passes are only darkened by fog, not tinted
2719 if (r_glsl_permutation->loc_FogColor >= 0)
2720 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2721 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2725 if (mode == SHADERMODE_FLATCOLOR)
2727 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2729 else if (mode == SHADERMODE_LIGHTDIRECTION)
2731 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]);
2732 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]);
2733 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);
2734 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);
2735 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);
2736 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]);
2737 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]);
2741 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]);
2742 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]);
2743 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);
2744 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);
2745 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);
2747 // additive passes are only darkened by fog, not tinted
2748 if (r_glsl_permutation->loc_FogColor >= 0)
2750 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2751 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2753 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2755 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);
2756 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]);
2757 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]);
2758 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]);
2759 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]);
2760 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2761 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2762 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2763 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]);
2765 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2766 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2767 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2768 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]);
2769 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]);
2771 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2772 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));
2773 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2774 if (r_glsl_permutation->loc_Color_Pants >= 0)
2776 if (rsurface.texture->pantstexture)
2777 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2779 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2781 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2783 if (rsurface.texture->shirttexture)
2784 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2786 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2788 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]);
2789 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2790 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2791 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2792 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2793 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2794 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2795 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2796 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2798 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2799 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2800 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]);
2801 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2802 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);}
2803 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2805 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2806 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2807 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2808 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2809 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2810 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2811 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2812 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2813 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2814 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2815 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2816 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2817 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2818 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2819 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);
2820 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2821 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2822 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2823 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2824 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2825 if (rsurfacepass == RSURFPASS_BACKGROUND)
2827 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);
2828 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);
2829 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);
2833 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);
2835 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2836 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2837 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2838 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2839 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2841 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2842 if (rsurface.rtlight)
2844 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2845 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2848 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2851 case RENDERPATH_GL11:
2852 case RENDERPATH_GL13:
2853 case RENDERPATH_GLES1:
2855 case RENDERPATH_SOFT:
2856 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);
2857 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2858 R_SetupShader_SetPermutationSoft(mode, permutation);
2859 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2860 if (mode == SHADERMODE_LIGHTSOURCE)
2862 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2863 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2864 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2865 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2866 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2869 // additive passes are only darkened by fog, not tinted
2870 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2871 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2875 if (mode == SHADERMODE_FLATCOLOR)
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2879 else if (mode == SHADERMODE_LIGHTDIRECTION)
2881 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]);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2883 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);
2884 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);
2885 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2886 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]);
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2891 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2893 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);
2894 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);
2895 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2897 // additive passes are only darkened by fog, not tinted
2898 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2902 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);
2903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2904 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2905 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]);
2906 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]);
2907 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2908 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2909 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2910 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2912 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2913 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2914 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2915 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2916 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]);
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2919 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));
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2921 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2923 if (rsurface.texture->pantstexture)
2924 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2926 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2928 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2930 if (rsurface.texture->shirttexture)
2931 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2935 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2936 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2937 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2938 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2939 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2940 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2941 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2942 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2943 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2945 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2946 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2947 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2948 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2950 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2951 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2952 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2953 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2954 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2955 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2956 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2957 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2958 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2959 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2960 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2961 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2962 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2963 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2964 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2965 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2966 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2967 if (rsurfacepass == RSURFPASS_BACKGROUND)
2969 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2970 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2971 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2975 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2977 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2978 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2979 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2980 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2981 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2983 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2984 if (rsurface.rtlight)
2986 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2987 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2994 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2996 // select a permutation of the lighting shader appropriate to this
2997 // combination of texture, entity, light source, and fogging, only use the
2998 // minimum features necessary to avoid wasting rendering time in the
2999 // fragment shader on features that are not being used
3000 unsigned int permutation = 0;
3001 unsigned int mode = 0;
3002 const float *lightcolorbase = rtlight->currentcolor;
3003 float ambientscale = rtlight->ambientscale;
3004 float diffusescale = rtlight->diffusescale;
3005 float specularscale = rtlight->specularscale;
3006 // this is the location of the light in view space
3007 vec3_t viewlightorigin;
3008 // this transforms from view space (camera) to light space (cubemap)
3009 matrix4x4_t viewtolight;
3010 matrix4x4_t lighttoview;
3011 float viewtolight16f[16];
3012 float range = 1.0f / r_shadow_deferred_8bitrange.value;
3014 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3015 if (rtlight->currentcubemap != r_texture_whitecube)
3016 permutation |= SHADERPERMUTATION_CUBEFILTER;
3017 if (diffusescale > 0)
3018 permutation |= SHADERPERMUTATION_DIFFUSE;
3019 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3020 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3021 if (r_shadow_usingshadowmap2d)
3023 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3024 if (r_shadow_shadowmapvsdct)
3025 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3027 if (r_shadow_shadowmapsampler)
3028 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3029 if (r_shadow_shadowmappcf > 1)
3030 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3031 else if (r_shadow_shadowmappcf)
3032 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3034 if (vid.allowalphatocoverage)
3035 GL_AlphaToCoverage(false);
3036 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3037 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3038 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3039 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3040 switch(vid.renderpath)
3042 case RENDERPATH_D3D9:
3044 R_SetupShader_SetPermutationHLSL(mode, permutation);
3045 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3046 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3047 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3048 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3049 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3050 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3051 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3052 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3053 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3054 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3056 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3057 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
3058 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3059 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3060 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
3061 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3064 case RENDERPATH_D3D10:
3065 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3067 case RENDERPATH_D3D11:
3068 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3070 case RENDERPATH_GL20:
3071 case RENDERPATH_GLES2:
3072 R_SetupShader_SetPermutationGLSL(mode, permutation);
3073 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3074 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3075 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);
3076 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);
3077 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);
3078 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]);
3079 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]);
3080 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f( r_glsl_permutation->loc_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3081 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]);
3082 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3084 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3085 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
3086 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3087 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3088 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
3089 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3091 case RENDERPATH_GL11:
3092 case RENDERPATH_GL13:
3093 case RENDERPATH_GLES1:
3095 case RENDERPATH_SOFT:
3096 R_SetupShader_SetPermutationGLSL(mode, permutation);
3097 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3098 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3099 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
3100 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
3101 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3102 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3103 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]);
3104 DPSOFTRAST_Uniform1f( DPSOFTRAST_UNIFORM_SpecularPower , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3105 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3106 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3108 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3109 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3110 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3111 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3112 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3113 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3118 #define SKINFRAME_HASH 1024
3122 int loadsequence; // incremented each level change
3123 memexpandablearray_t array;
3124 skinframe_t *hash[SKINFRAME_HASH];
3127 r_skinframe_t r_skinframe;
3129 void R_SkinFrame_PrepareForPurge(void)
3131 r_skinframe.loadsequence++;
3132 // wrap it without hitting zero
3133 if (r_skinframe.loadsequence >= 200)
3134 r_skinframe.loadsequence = 1;
3137 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3141 // mark the skinframe as used for the purging code
3142 skinframe->loadsequence = r_skinframe.loadsequence;
3145 void R_SkinFrame_Purge(void)
3149 for (i = 0;i < SKINFRAME_HASH;i++)
3151 for (s = r_skinframe.hash[i];s;s = s->next)
3153 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3155 if (s->merged == s->base)
3157 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3158 R_PurgeTexture(s->stain );s->stain = NULL;
3159 R_PurgeTexture(s->merged);s->merged = NULL;
3160 R_PurgeTexture(s->base );s->base = NULL;
3161 R_PurgeTexture(s->pants );s->pants = NULL;
3162 R_PurgeTexture(s->shirt );s->shirt = NULL;
3163 R_PurgeTexture(s->nmap );s->nmap = NULL;
3164 R_PurgeTexture(s->gloss );s->gloss = NULL;
3165 R_PurgeTexture(s->glow );s->glow = NULL;
3166 R_PurgeTexture(s->fog );s->fog = NULL;
3167 R_PurgeTexture(s->reflect);s->reflect = NULL;
3168 s->loadsequence = 0;
3174 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3176 char basename[MAX_QPATH];
3178 Image_StripImageExtension(name, basename, sizeof(basename));
3180 if( last == NULL ) {
3182 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3183 item = r_skinframe.hash[hashindex];
3188 // linearly search through the hash bucket
3189 for( ; item ; item = item->next ) {
3190 if( !strcmp( item->basename, basename ) ) {
3197 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3201 char basename[MAX_QPATH];
3203 Image_StripImageExtension(name, basename, sizeof(basename));
3205 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3206 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3207 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3211 rtexture_t *dyntexture;
3212 // check whether its a dynamic texture
3213 dyntexture = CL_GetDynTexture( basename );
3214 if (!add && !dyntexture)
3216 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3217 memset(item, 0, sizeof(*item));
3218 strlcpy(item->basename, basename, sizeof(item->basename));
3219 item->base = dyntexture; // either NULL or dyntexture handle
3220 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3221 item->comparewidth = comparewidth;
3222 item->compareheight = compareheight;
3223 item->comparecrc = comparecrc;
3224 item->next = r_skinframe.hash[hashindex];
3225 r_skinframe.hash[hashindex] = item;
3227 else if (textureflags & TEXF_FORCE_RELOAD)
3229 rtexture_t *dyntexture;
3230 // check whether its a dynamic texture
3231 dyntexture = CL_GetDynTexture( basename );
3232 if (!add && !dyntexture)
3234 if (item->merged == item->base)
3235 item->merged = NULL;
3236 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3237 R_PurgeTexture(item->stain );item->stain = NULL;
3238 R_PurgeTexture(item->merged);item->merged = NULL;
3239 R_PurgeTexture(item->base );item->base = NULL;
3240 R_PurgeTexture(item->pants );item->pants = NULL;
3241 R_PurgeTexture(item->shirt );item->shirt = NULL;
3242 R_PurgeTexture(item->nmap );item->nmap = NULL;
3243 R_PurgeTexture(item->gloss );item->gloss = NULL;
3244 R_PurgeTexture(item->glow );item->glow = NULL;
3245 R_PurgeTexture(item->fog );item->fog = NULL;
3246 R_PurgeTexture(item->reflect);item->reflect = NULL;
3247 item->loadsequence = 0;
3249 else if( item->base == NULL )
3251 rtexture_t *dyntexture;
3252 // check whether its a dynamic texture
3253 // 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]
3254 dyntexture = CL_GetDynTexture( basename );
3255 item->base = dyntexture; // either NULL or dyntexture handle
3258 R_SkinFrame_MarkUsed(item);
3262 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3264 unsigned long long avgcolor[5], wsum; \
3272 for(pix = 0; pix < cnt; ++pix) \
3275 for(comp = 0; comp < 3; ++comp) \
3277 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3280 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3282 for(comp = 0; comp < 3; ++comp) \
3283 avgcolor[comp] += getpixel * w; \
3286 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3287 avgcolor[4] += getpixel; \
3289 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3291 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3292 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3293 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3294 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3297 extern cvar_t gl_picmip;
3298 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3301 unsigned char *pixels;
3302 unsigned char *bumppixels;
3303 unsigned char *basepixels = NULL;
3304 int basepixels_width = 0;
3305 int basepixels_height = 0;
3306 skinframe_t *skinframe;
3307 rtexture_t *ddsbase = NULL;
3308 qboolean ddshasalpha = false;
3309 float ddsavgcolor[4];
3310 char basename[MAX_QPATH];
3311 int miplevel = R_PicmipForFlags(textureflags);
3312 int savemiplevel = miplevel;
3315 if (cls.state == ca_dedicated)
3318 // return an existing skinframe if already loaded
3319 // if loading of the first image fails, don't make a new skinframe as it
3320 // would cause all future lookups of this to be missing
3321 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3322 if (skinframe && skinframe->base)
3325 Image_StripImageExtension(name, basename, sizeof(basename));
3327 // check for DDS texture file first
3328 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3330 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3331 if (basepixels == NULL)
3335 // FIXME handle miplevel
3337 if (developer_loading.integer)
3338 Con_Printf("loading skin \"%s\"\n", name);
3340 // we've got some pixels to store, so really allocate this new texture now
3342 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3343 textureflags &= ~TEXF_FORCE_RELOAD;
3344 skinframe->stain = NULL;
3345 skinframe->merged = NULL;
3346 skinframe->base = NULL;
3347 skinframe->pants = NULL;
3348 skinframe->shirt = NULL;
3349 skinframe->nmap = NULL;
3350 skinframe->gloss = NULL;
3351 skinframe->glow = NULL;
3352 skinframe->fog = NULL;
3353 skinframe->reflect = NULL;
3354 skinframe->hasalpha = false;
3358 skinframe->base = ddsbase;
3359 skinframe->hasalpha = ddshasalpha;
3360 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3361 if (r_loadfog && skinframe->hasalpha)
3362 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3363 //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]);
3367 basepixels_width = image_width;
3368 basepixels_height = image_height;
3369 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);
3370 if (textureflags & TEXF_ALPHA)
3372 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3374 if (basepixels[j] < 255)
3376 skinframe->hasalpha = true;
3380 if (r_loadfog && skinframe->hasalpha)
3382 // has transparent pixels
3383 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3384 for (j = 0;j < image_width * image_height * 4;j += 4)
3389 pixels[j+3] = basepixels[j+3];
3391 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);
3395 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3397 //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]);
3398 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3399 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3400 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3401 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3407 mymiplevel = savemiplevel;
3408 if (r_loadnormalmap)
3409 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);
3410 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3412 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3413 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3414 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3415 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3418 // _norm is the name used by tenebrae and has been adopted as standard
3419 if (r_loadnormalmap && skinframe->nmap == NULL)
3421 mymiplevel = savemiplevel;
3422 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3424 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);
3428 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3430 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3431 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3432 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);
3434 Mem_Free(bumppixels);
3436 else if (r_shadow_bumpscale_basetexture.value > 0)
3438 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3439 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3440 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);
3444 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3445 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3449 // _luma is supported only for tenebrae compatibility
3450 // _glow is the preferred name
3451 mymiplevel = savemiplevel;
3452 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))))
3454 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);
3456 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3457 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3459 Mem_Free(pixels);pixels = NULL;
3462 mymiplevel = savemiplevel;
3463 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3465 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3467 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3468 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3474 mymiplevel = savemiplevel;
3475 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3477 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);
3479 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3480 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3486 mymiplevel = savemiplevel;
3487 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3489 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);
3491 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3492 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3498 mymiplevel = savemiplevel;
3499 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3501 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);
3503 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3504 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3511 Mem_Free(basepixels);
3516 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3517 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3520 unsigned char *temp1, *temp2;
3521 skinframe_t *skinframe;
3523 if (cls.state == ca_dedicated)
3526 // if already loaded just return it, otherwise make a new skinframe
3527 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3528 if (skinframe && skinframe->base)
3530 textureflags &= ~TEXF_FORCE_RELOAD;
3532 skinframe->stain = NULL;
3533 skinframe->merged = NULL;
3534 skinframe->base = NULL;
3535 skinframe->pants = NULL;
3536 skinframe->shirt = NULL;
3537 skinframe->nmap = NULL;
3538 skinframe->gloss = NULL;
3539 skinframe->glow = NULL;
3540 skinframe->fog = NULL;
3541 skinframe->reflect = NULL;
3542 skinframe->hasalpha = false;
3544 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3548 if (developer_loading.integer)
3549 Con_Printf("loading 32bit skin \"%s\"\n", name);
3551 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3553 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3554 temp2 = temp1 + width * height * 4;
3555 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3556 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);
3559 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3560 if (textureflags & TEXF_ALPHA)
3562 for (i = 3;i < width * height * 4;i += 4)
3564 if (skindata[i] < 255)
3566 skinframe->hasalpha = true;
3570 if (r_loadfog && skinframe->hasalpha)
3572 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3573 memcpy(fogpixels, skindata, width * height * 4);
3574 for (i = 0;i < width * height * 4;i += 4)
3575 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3576 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3577 Mem_Free(fogpixels);
3581 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3582 //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]);
3587 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3591 skinframe_t *skinframe;
3593 if (cls.state == ca_dedicated)
3596 // if already loaded just return it, otherwise make a new skinframe
3597 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3598 if (skinframe && skinframe->base)
3600 textureflags &= ~TEXF_FORCE_RELOAD;
3602 skinframe->stain = NULL;
3603 skinframe->merged = NULL;
3604 skinframe->base = NULL;
3605 skinframe->pants = NULL;
3606 skinframe->shirt = NULL;
3607 skinframe->nmap = NULL;
3608 skinframe->gloss = NULL;
3609 skinframe->glow = NULL;
3610 skinframe->fog = NULL;
3611 skinframe->reflect = NULL;
3612 skinframe->hasalpha = false;
3614 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3618 if (developer_loading.integer)
3619 Con_Printf("loading quake skin \"%s\"\n", name);
3621 // 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)
3622 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3623 memcpy(skinframe->qpixels, skindata, width*height);
3624 skinframe->qwidth = width;
3625 skinframe->qheight = height;
3628 for (i = 0;i < width * height;i++)
3629 featuresmask |= palette_featureflags[skindata[i]];
3631 skinframe->hasalpha = false;
3632 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3633 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3634 skinframe->qgeneratemerged = true;
3635 skinframe->qgeneratebase = skinframe->qhascolormapping;
3636 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3638 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3639 //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]);
3644 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3648 unsigned char *skindata;
3650 if (!skinframe->qpixels)
3653 if (!skinframe->qhascolormapping)
3654 colormapped = false;
3658 if (!skinframe->qgeneratebase)
3663 if (!skinframe->qgeneratemerged)
3667 width = skinframe->qwidth;
3668 height = skinframe->qheight;
3669 skindata = skinframe->qpixels;
3671 if (skinframe->qgeneratenmap)
3673 unsigned char *temp1, *temp2;
3674 skinframe->qgeneratenmap = false;
3675 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3676 temp2 = temp1 + width * height * 4;
3677 // use either a custom palette or the quake palette
3678 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3679 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3680 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);
3684 if (skinframe->qgenerateglow)
3686 skinframe->qgenerateglow = false;
3687 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
3692 skinframe->qgeneratebase = false;
3693 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);
3694 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);
3695 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);
3699 skinframe->qgeneratemerged = false;
3700 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);
3703 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3705 Mem_Free(skinframe->qpixels);
3706 skinframe->qpixels = NULL;
3710 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)
3713 skinframe_t *skinframe;
3715 if (cls.state == ca_dedicated)
3718 // if already loaded just return it, otherwise make a new skinframe
3719 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3720 if (skinframe && skinframe->base)
3722 textureflags &= ~TEXF_FORCE_RELOAD;
3724 skinframe->stain = NULL;
3725 skinframe->merged = NULL;
3726 skinframe->base = NULL;
3727 skinframe->pants = NULL;
3728 skinframe->shirt = NULL;
3729 skinframe->nmap = NULL;
3730 skinframe->gloss = NULL;
3731 skinframe->glow = NULL;
3732 skinframe->fog = NULL;
3733 skinframe->reflect = NULL;
3734 skinframe->hasalpha = false;
3736 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3740 if (developer_loading.integer)
3741 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3743 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3744 if (textureflags & TEXF_ALPHA)
3746 for (i = 0;i < width * height;i++)
3748 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3750 skinframe->hasalpha = true;
3754 if (r_loadfog && skinframe->hasalpha)
3755 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3758 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3759 //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]);
3764 skinframe_t *R_SkinFrame_LoadMissing(void)
3766 skinframe_t *skinframe;
3768 if (cls.state == ca_dedicated)
3771 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3772 skinframe->stain = NULL;
3773 skinframe->merged = NULL;
3774 skinframe->base = NULL;
3775 skinframe->pants = NULL;
3776 skinframe->shirt = NULL;
3777 skinframe->nmap = NULL;
3778 skinframe->gloss = NULL;
3779 skinframe->glow = NULL;
3780 skinframe->fog = NULL;
3781 skinframe->reflect = NULL;
3782 skinframe->hasalpha = false;
3784 skinframe->avgcolor[0] = rand() / RAND_MAX;
3785 skinframe->avgcolor[1] = rand() / RAND_MAX;
3786 skinframe->avgcolor[2] = rand() / RAND_MAX;
3787 skinframe->avgcolor[3] = 1;
3792 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3793 typedef struct suffixinfo_s
3796 qboolean flipx, flipy, flipdiagonal;
3799 static suffixinfo_t suffix[3][6] =
3802 {"px", false, false, false},
3803 {"nx", false, false, false},
3804 {"py", false, false, false},
3805 {"ny", false, false, false},
3806 {"pz", false, false, false},
3807 {"nz", false, false, false}
3810 {"posx", false, false, false},
3811 {"negx", false, false, false},
3812 {"posy", false, false, false},
3813 {"negy", false, false, false},
3814 {"posz", false, false, false},
3815 {"negz", false, false, false}
3818 {"rt", true, false, true},
3819 {"lf", false, true, true},
3820 {"ft", true, true, false},
3821 {"bk", false, false, false},
3822 {"up", true, false, true},
3823 {"dn", true, false, true}
3827 static int componentorder[4] = {0, 1, 2, 3};
3829 rtexture_t *R_LoadCubemap(const char *basename)
3831 int i, j, cubemapsize;
3832 unsigned char *cubemappixels, *image_buffer;
3833 rtexture_t *cubemaptexture;
3835 // must start 0 so the first loadimagepixels has no requested width/height
3837 cubemappixels = NULL;
3838 cubemaptexture = NULL;
3839 // keep trying different suffix groups (posx, px, rt) until one loads
3840 for (j = 0;j < 3 && !cubemappixels;j++)
3842 // load the 6 images in the suffix group
3843 for (i = 0;i < 6;i++)
3845 // generate an image name based on the base and and suffix
3846 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3848 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3850 // an image loaded, make sure width and height are equal
3851 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3853 // if this is the first image to load successfully, allocate the cubemap memory
3854 if (!cubemappixels && image_width >= 1)
3856 cubemapsize = image_width;
3857 // note this clears to black, so unavailable sides are black
3858 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3860 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3862 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);
3865 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3867 Mem_Free(image_buffer);
3871 // if a cubemap loaded, upload it
3874 if (developer_loading.integer)
3875 Con_Printf("loading cubemap \"%s\"\n", basename);
3877 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);
3878 Mem_Free(cubemappixels);
3882 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3883 if (developer_loading.integer)
3885 Con_Printf("(tried tried images ");
3886 for (j = 0;j < 3;j++)
3887 for (i = 0;i < 6;i++)
3888 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3889 Con_Print(" and was unable to find any of them).\n");
3892 return cubemaptexture;
3895 rtexture_t *R_GetCubemap(const char *basename)
3898 for (i = 0;i < r_texture_numcubemaps;i++)
3899 if (r_texture_cubemaps[i] != NULL)
3900 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3901 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3902 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3903 return r_texture_whitecube;
3904 r_texture_numcubemaps++;
3905 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3906 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3907 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3908 return r_texture_cubemaps[i]->texture;
3911 void R_FreeCubemap(const char *basename)
3915 for (i = 0;i < r_texture_numcubemaps;i++)
3917 if (r_texture_cubemaps[i] != NULL)
3919 if (r_texture_cubemaps[i]->texture)
3921 if (developer_loading.integer)
3922 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3923 R_FreeTexture(r_texture_cubemaps[i]->texture);
3924 Mem_Free(r_texture_cubemaps[i]);
3925 r_texture_cubemaps[i] = NULL;
3931 void R_FreeCubemaps(void)
3934 for (i = 0;i < r_texture_numcubemaps;i++)
3936 if (developer_loading.integer)
3937 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3938 if (r_texture_cubemaps[i] != NULL)
3940 if (r_texture_cubemaps[i]->texture)
3941 R_FreeTexture(r_texture_cubemaps[i]->texture);
3942 Mem_Free(r_texture_cubemaps[i]);
3945 r_texture_numcubemaps = 0;
3948 void R_Main_FreeViewCache(void)
3950 if (r_refdef.viewcache.entityvisible)
3951 Mem_Free(r_refdef.viewcache.entityvisible);
3952 if (r_refdef.viewcache.world_pvsbits)
3953 Mem_Free(r_refdef.viewcache.world_pvsbits);
3954 if (r_refdef.viewcache.world_leafvisible)
3955 Mem_Free(r_refdef.viewcache.world_leafvisible);
3956 if (r_refdef.viewcache.world_surfacevisible)
3957 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3958 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3961 void R_Main_ResizeViewCache(void)
3963 int numentities = r_refdef.scene.numentities;
3964 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3965 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3966 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3967 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3968 if (r_refdef.viewcache.maxentities < numentities)
3970 r_refdef.viewcache.maxentities = numentities;
3971 if (r_refdef.viewcache.entityvisible)
3972 Mem_Free(r_refdef.viewcache.entityvisible);
3973 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3975 if (r_refdef.viewcache.world_numclusters != numclusters)
3977 r_refdef.viewcache.world_numclusters = numclusters;
3978 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3979 if (r_refdef.viewcache.world_pvsbits)
3980 Mem_Free(r_refdef.viewcache.world_pvsbits);
3981 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3983 if (r_refdef.viewcache.world_numleafs != numleafs)
3985 r_refdef.viewcache.world_numleafs = numleafs;
3986 if (r_refdef.viewcache.world_leafvisible)
3987 Mem_Free(r_refdef.viewcache.world_leafvisible);
3988 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3990 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3992 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3993 if (r_refdef.viewcache.world_surfacevisible)
3994 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3995 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3999 extern rtexture_t *loadingscreentexture;
4000 void gl_main_start(void)
4002 loadingscreentexture = NULL;
4003 r_texture_blanknormalmap = NULL;
4004 r_texture_white = NULL;
4005 r_texture_grey128 = NULL;
4006 r_texture_black = NULL;
4007 r_texture_whitecube = NULL;
4008 r_texture_normalizationcube = NULL;
4009 r_texture_fogattenuation = NULL;
4010 r_texture_fogheighttexture = NULL;
4011 r_texture_gammaramps = NULL;
4012 r_texture_numcubemaps = 0;
4014 r_loaddds = r_texture_dds_load.integer != 0;
4015 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4017 switch(vid.renderpath)
4019 case RENDERPATH_GL20:
4020 case RENDERPATH_D3D9:
4021 case RENDERPATH_D3D10:
4022 case RENDERPATH_D3D11:
4023 case RENDERPATH_SOFT:
4024 case RENDERPATH_GLES2:
4025 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4026 Cvar_SetValueQuick(&gl_combine, 1);
4027 Cvar_SetValueQuick(&r_glsl, 1);
4028 r_loadnormalmap = true;
4032 case RENDERPATH_GL13:
4033 case RENDERPATH_GLES1:
4034 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4035 Cvar_SetValueQuick(&gl_combine, 1);
4036 Cvar_SetValueQuick(&r_glsl, 0);
4037 r_loadnormalmap = false;
4038 r_loadgloss = false;
4041 case RENDERPATH_GL11:
4042 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4043 Cvar_SetValueQuick(&gl_combine, 0);
4044 Cvar_SetValueQuick(&r_glsl, 0);
4045 r_loadnormalmap = false;
4046 r_loadgloss = false;
4052 R_FrameData_Reset();
4056 memset(r_queries, 0, sizeof(r_queries));
4058 r_qwskincache = NULL;
4059 r_qwskincache_size = 0;
4061 // due to caching of texture_t references, the collision cache must be reset
4062 Collision_Cache_Reset(true);
4064 // set up r_skinframe loading system for textures
4065 memset(&r_skinframe, 0, sizeof(r_skinframe));
4066 r_skinframe.loadsequence = 1;
4067 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4069 r_main_texturepool = R_AllocTexturePool();
4070 R_BuildBlankTextures();
4072 if (vid.support.arb_texture_cube_map)
4075 R_BuildNormalizationCube();
4077 r_texture_fogattenuation = NULL;
4078 r_texture_fogheighttexture = NULL;
4079 r_texture_gammaramps = NULL;
4080 //r_texture_fogintensity = NULL;
4081 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4082 memset(&r_waterstate, 0, sizeof(r_waterstate));
4083 r_glsl_permutation = NULL;
4084 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4085 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4086 glslshaderstring = NULL;
4088 r_hlsl_permutation = NULL;
4089 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4090 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4092 hlslshaderstring = NULL;
4093 memset(&r_svbsp, 0, sizeof (r_svbsp));
4095 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4096 r_texture_numcubemaps = 0;
4098 r_refdef.fogmasktable_density = 0;
4101 void gl_main_shutdown(void)
4104 R_FrameData_Reset();
4106 R_Main_FreeViewCache();
4108 switch(vid.renderpath)
4110 case RENDERPATH_GL11:
4111 case RENDERPATH_GL13:
4112 case RENDERPATH_GL20:
4113 case RENDERPATH_GLES1:
4114 case RENDERPATH_GLES2:
4115 #ifdef GL_SAMPLES_PASSED_ARB
4117 qglDeleteQueriesARB(r_maxqueries, r_queries);
4120 case RENDERPATH_D3D9:
4121 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4123 case RENDERPATH_D3D10:
4124 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4126 case RENDERPATH_D3D11:
4127 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4129 case RENDERPATH_SOFT:
4135 memset(r_queries, 0, sizeof(r_queries));
4137 r_qwskincache = NULL;
4138 r_qwskincache_size = 0;
4140 // clear out the r_skinframe state
4141 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4142 memset(&r_skinframe, 0, sizeof(r_skinframe));
4145 Mem_Free(r_svbsp.nodes);
4146 memset(&r_svbsp, 0, sizeof (r_svbsp));
4147 R_FreeTexturePool(&r_main_texturepool);
4148 loadingscreentexture = NULL;
4149 r_texture_blanknormalmap = NULL;
4150 r_texture_white = NULL;
4151 r_texture_grey128 = NULL;
4152 r_texture_black = NULL;
4153 r_texture_whitecube = NULL;
4154 r_texture_normalizationcube = NULL;
4155 r_texture_fogattenuation = NULL;
4156 r_texture_fogheighttexture = NULL;
4157 r_texture_gammaramps = NULL;
4158 r_texture_numcubemaps = 0;
4159 //r_texture_fogintensity = NULL;
4160 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4161 memset(&r_waterstate, 0, sizeof(r_waterstate));
4164 r_glsl_permutation = NULL;
4165 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4166 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4167 glslshaderstring = NULL;
4169 r_hlsl_permutation = NULL;
4170 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4171 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4173 hlslshaderstring = NULL;
4176 extern void CL_ParseEntityLump(char *entitystring);
4177 void gl_main_newmap(void)
4179 // FIXME: move this code to client
4180 char *entities, entname[MAX_QPATH];
4182 Mem_Free(r_qwskincache);
4183 r_qwskincache = NULL;
4184 r_qwskincache_size = 0;
4187 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4188 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4190 CL_ParseEntityLump(entities);
4194 if (cl.worldmodel->brush.entities)
4195 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4197 R_Main_FreeViewCache();
4199 R_FrameData_Reset();
4202 void GL_Main_Init(void)
4204 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4206 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4207 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4208 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4209 if (gamemode == GAME_NEHAHRA)
4211 Cvar_RegisterVariable (&gl_fogenable);
4212 Cvar_RegisterVariable (&gl_fogdensity);
4213 Cvar_RegisterVariable (&gl_fogred);
4214 Cvar_RegisterVariable (&gl_foggreen);
4215 Cvar_RegisterVariable (&gl_fogblue);
4216 Cvar_RegisterVariable (&gl_fogstart);
4217 Cvar_RegisterVariable (&gl_fogend);
4218 Cvar_RegisterVariable (&gl_skyclip);
4220 Cvar_RegisterVariable(&r_motionblur);
4221 Cvar_RegisterVariable(&r_damageblur);
4222 Cvar_RegisterVariable(&r_motionblur_averaging);
4223 Cvar_RegisterVariable(&r_motionblur_randomize);
4224 Cvar_RegisterVariable(&r_motionblur_minblur);
4225 Cvar_RegisterVariable(&r_motionblur_maxblur);
4226 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4227 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4228 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4229 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4230 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4231 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4232 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4233 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4234 Cvar_RegisterVariable(&r_equalize_entities_by);
4235 Cvar_RegisterVariable(&r_equalize_entities_to);
4236 Cvar_RegisterVariable(&r_depthfirst);
4237 Cvar_RegisterVariable(&r_useinfinitefarclip);
4238 Cvar_RegisterVariable(&r_farclip_base);
4239 Cvar_RegisterVariable(&r_farclip_world);
4240 Cvar_RegisterVariable(&r_nearclip);
4241 Cvar_RegisterVariable(&r_deformvertexes);
4242 Cvar_RegisterVariable(&r_transparent);
4243 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4244 Cvar_RegisterVariable(&r_showoverdraw);
4245 Cvar_RegisterVariable(&r_showbboxes);
4246 Cvar_RegisterVariable(&r_showsurfaces);
4247 Cvar_RegisterVariable(&r_showtris);
4248 Cvar_RegisterVariable(&r_shownormals);
4249 Cvar_RegisterVariable(&r_showlighting);
4250 Cvar_RegisterVariable(&r_showshadowvolumes);
4251 Cvar_RegisterVariable(&r_showcollisionbrushes);
4252 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4253 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4254 Cvar_RegisterVariable(&r_showdisabledepthtest);
4255 Cvar_RegisterVariable(&r_drawportals);
4256 Cvar_RegisterVariable(&r_drawentities);
4257 Cvar_RegisterVariable(&r_draw2d);
4258 Cvar_RegisterVariable(&r_drawworld);
4259 Cvar_RegisterVariable(&r_cullentities_trace);
4260 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4261 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4262 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4263 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4264 Cvar_RegisterVariable(&r_sortentities);
4265 Cvar_RegisterVariable(&r_drawviewmodel);
4266 Cvar_RegisterVariable(&r_drawexteriormodel);
4267 Cvar_RegisterVariable(&r_speeds);
4268 Cvar_RegisterVariable(&r_fullbrights);
4269 Cvar_RegisterVariable(&r_wateralpha);
4270 Cvar_RegisterVariable(&r_dynamic);
4271 Cvar_RegisterVariable(&r_fakelight);
4272 Cvar_RegisterVariable(&r_fakelight_intensity);
4273 Cvar_RegisterVariable(&r_fullbright);
4274 Cvar_RegisterVariable(&r_shadows);
4275 Cvar_RegisterVariable(&r_shadows_darken);
4276 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4277 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4278 Cvar_RegisterVariable(&r_shadows_throwdistance);
4279 Cvar_RegisterVariable(&r_shadows_throwdirection);
4280 Cvar_RegisterVariable(&r_shadows_focus);
4281 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4282 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4283 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4284 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4285 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4286 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4287 Cvar_RegisterVariable(&r_fog_exp2);
4288 Cvar_RegisterVariable(&r_fog_clear);
4289 Cvar_RegisterVariable(&r_drawfog);
4290 Cvar_RegisterVariable(&r_transparentdepthmasking);
4291 Cvar_RegisterVariable(&r_transparent_sortmindist);
4292 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4293 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4294 Cvar_RegisterVariable(&r_texture_dds_load);
4295 Cvar_RegisterVariable(&r_texture_dds_save);
4296 Cvar_RegisterVariable(&r_textureunits);
4297 Cvar_RegisterVariable(&gl_combine);
4298 Cvar_RegisterVariable(&r_viewfbo);
4299 Cvar_RegisterVariable(&r_viewscale);
4300 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4301 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4302 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4303 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4304 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4305 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4306 Cvar_RegisterVariable(&r_glsl);
4307 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4308 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4309 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4310 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4311 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4312 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4313 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4314 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4315 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4316 Cvar_RegisterVariable(&r_glsl_postprocess);
4317 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4318 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4319 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4320 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4321 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4322 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4323 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4324 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4326 Cvar_RegisterVariable(&r_water);
4327 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4328 Cvar_RegisterVariable(&r_water_clippingplanebias);
4329 Cvar_RegisterVariable(&r_water_refractdistort);
4330 Cvar_RegisterVariable(&r_water_reflectdistort);
4331 Cvar_RegisterVariable(&r_water_scissormode);
4332 Cvar_RegisterVariable(&r_water_lowquality);
4333 Cvar_RegisterVariable(&r_water_hideplayer);
4335 Cvar_RegisterVariable(&r_lerpsprites);
4336 Cvar_RegisterVariable(&r_lerpmodels);
4337 Cvar_RegisterVariable(&r_lerplightstyles);
4338 Cvar_RegisterVariable(&r_waterscroll);
4339 Cvar_RegisterVariable(&r_bloom);
4340 Cvar_RegisterVariable(&r_bloom_colorscale);
4341 Cvar_RegisterVariable(&r_bloom_brighten);
4342 Cvar_RegisterVariable(&r_bloom_blur);
4343 Cvar_RegisterVariable(&r_bloom_resolution);
4344 Cvar_RegisterVariable(&r_bloom_colorexponent);
4345 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4346 Cvar_RegisterVariable(&r_hdr);
4347 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4348 Cvar_RegisterVariable(&r_hdr_glowintensity);
4349 Cvar_RegisterVariable(&r_hdr_range);
4350 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4351 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4352 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4353 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4354 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4355 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4356 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4357 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4358 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4359 Cvar_RegisterVariable(&developer_texturelogging);
4360 Cvar_RegisterVariable(&gl_lightmaps);
4361 Cvar_RegisterVariable(&r_test);
4362 Cvar_RegisterVariable(&r_glsl_saturation);
4363 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4364 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4365 Cvar_RegisterVariable(&r_framedatasize);
4366 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4367 Cvar_SetValue("r_fullbrights", 0);
4368 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4371 extern void R_Textures_Init(void);
4372 extern void GL_Draw_Init(void);
4373 extern void GL_Main_Init(void);
4374 extern void R_Shadow_Init(void);
4375 extern void R_Sky_Init(void);
4376 extern void GL_Surf_Init(void);
4377 extern void R_Particles_Init(void);
4378 extern void R_Explosion_Init(void);
4379 extern void gl_backend_init(void);
4380 extern void Sbar_Init(void);
4381 extern void R_LightningBeams_Init(void);
4382 extern void Mod_RenderInit(void);
4383 extern void Font_Init(void);
4385 void Render_Init(void)
4398 R_LightningBeams_Init();
4408 extern char *ENGINE_EXTENSIONS;
4411 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4412 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4413 gl_version = (const char *)qglGetString(GL_VERSION);
4414 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4418 if (!gl_platformextensions)
4419 gl_platformextensions = "";
4421 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4422 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4423 Con_Printf("GL_VERSION: %s\n", gl_version);
4424 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4425 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4427 VID_CheckExtensions();
4429 // LordHavoc: report supported extensions
4430 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4432 // clear to black (loading plaque will be seen over this)
4433 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4437 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4441 if (r_trippy.integer)
4443 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4445 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4448 p = r_refdef.view.frustum + i;
4453 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4457 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4461 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4465 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4469 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4473 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4477 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4481 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4489 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4493 if (r_trippy.integer)
4495 for (i = 0;i < numplanes;i++)
4502 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4506 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4510 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4514 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4518 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4522 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4526 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4530 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4538 //==================================================================================
4540 // LordHavoc: this stores temporary data used within the same frame
4542 typedef struct r_framedata_mem_s
4544 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4545 size_t size; // how much usable space
4546 size_t current; // how much space in use
4547 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4548 size_t wantedsize; // how much space was allocated
4549 unsigned char *data; // start of real data (16byte aligned)
4553 static r_framedata_mem_t *r_framedata_mem;
4555 void R_FrameData_Reset(void)
4557 while (r_framedata_mem)
4559 r_framedata_mem_t *next = r_framedata_mem->purge;
4560 Mem_Free(r_framedata_mem);
4561 r_framedata_mem = next;
4565 void R_FrameData_Resize(void)
4568 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4569 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4570 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4572 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4573 newmem->wantedsize = wantedsize;
4574 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4575 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4576 newmem->current = 0;
4578 newmem->purge = r_framedata_mem;
4579 r_framedata_mem = newmem;
4583 void R_FrameData_NewFrame(void)
4585 R_FrameData_Resize();
4586 if (!r_framedata_mem)
4588 // if we ran out of space on the last frame, free the old memory now
4589 while (r_framedata_mem->purge)
4591 // repeatedly remove the second item in the list, leaving only head
4592 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4593 Mem_Free(r_framedata_mem->purge);
4594 r_framedata_mem->purge = next;
4596 // reset the current mem pointer
4597 r_framedata_mem->current = 0;
4598 r_framedata_mem->mark = 0;
4601 void *R_FrameData_Alloc(size_t size)
4605 // align to 16 byte boundary - the data pointer is already aligned, so we
4606 // only need to ensure the size of every allocation is also aligned
4607 size = (size + 15) & ~15;
4609 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4611 // emergency - we ran out of space, allocate more memory
4612 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4613 R_FrameData_Resize();
4616 data = r_framedata_mem->data + r_framedata_mem->current;
4617 r_framedata_mem->current += size;
4619 // count the usage for stats
4620 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4621 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4623 return (void *)data;
4626 void *R_FrameData_Store(size_t size, void *data)
4628 void *d = R_FrameData_Alloc(size);
4630 memcpy(d, data, size);
4634 void R_FrameData_SetMark(void)
4636 if (!r_framedata_mem)
4638 r_framedata_mem->mark = r_framedata_mem->current;
4641 void R_FrameData_ReturnToMark(void)
4643 if (!r_framedata_mem)
4645 r_framedata_mem->current = r_framedata_mem->mark;
4648 //==================================================================================
4650 // LordHavoc: animcache originally written by Echon, rewritten since then
4653 * Animation cache prevents re-generating mesh data for an animated model
4654 * multiple times in one frame for lighting, shadowing, reflections, etc.
4657 void R_AnimCache_Free(void)
4661 void R_AnimCache_ClearCache(void)
4664 entity_render_t *ent;
4666 for (i = 0;i < r_refdef.scene.numentities;i++)
4668 ent = r_refdef.scene.entities[i];
4669 ent->animcache_vertex3f = NULL;
4670 ent->animcache_normal3f = NULL;
4671 ent->animcache_svector3f = NULL;
4672 ent->animcache_tvector3f = NULL;
4673 ent->animcache_vertexmesh = NULL;
4674 ent->animcache_vertex3fbuffer = NULL;
4675 ent->animcache_vertexmeshbuffer = NULL;
4679 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4683 // check if we need the meshbuffers
4684 if (!vid.useinterleavedarrays)
4687 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4688 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4689 // TODO: upload vertex3f buffer?
4690 if (ent->animcache_vertexmesh)
4692 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4693 for (i = 0;i < numvertices;i++)
4694 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4695 if (ent->animcache_svector3f)
4696 for (i = 0;i < numvertices;i++)
4697 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4698 if (ent->animcache_tvector3f)
4699 for (i = 0;i < numvertices;i++)
4700 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4701 if (ent->animcache_normal3f)
4702 for (i = 0;i < numvertices;i++)
4703 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4704 // TODO: upload vertexmeshbuffer?
4708 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4710 dp_model_t *model = ent->model;
4712 // see if it's already cached this frame
4713 if (ent->animcache_vertex3f)
4715 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4716 if (wantnormals || wanttangents)
4718 if (ent->animcache_normal3f)
4719 wantnormals = false;
4720 if (ent->animcache_svector3f)
4721 wanttangents = false;
4722 if (wantnormals || wanttangents)
4724 numvertices = model->surfmesh.num_vertices;
4726 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4729 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4730 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4732 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4733 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4739 // see if this ent is worth caching
4740 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4742 // get some memory for this entity and generate mesh data
4743 numvertices = model->surfmesh.num_vertices;
4744 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4746 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4749 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4750 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4752 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4753 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4758 void R_AnimCache_CacheVisibleEntities(void)
4761 qboolean wantnormals = true;
4762 qboolean wanttangents = !r_showsurfaces.integer;
4764 switch(vid.renderpath)
4766 case RENDERPATH_GL20:
4767 case RENDERPATH_D3D9:
4768 case RENDERPATH_D3D10:
4769 case RENDERPATH_D3D11:
4770 case RENDERPATH_GLES2:
4772 case RENDERPATH_GL11:
4773 case RENDERPATH_GL13:
4774 case RENDERPATH_GLES1:
4775 wanttangents = false;
4777 case RENDERPATH_SOFT:
4781 if (r_shownormals.integer)
4782 wanttangents = wantnormals = true;
4784 // TODO: thread this
4785 // NOTE: R_PrepareRTLights() also caches entities
4787 for (i = 0;i < r_refdef.scene.numentities;i++)
4788 if (r_refdef.viewcache.entityvisible[i])
4789 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4792 //==================================================================================
4794 extern cvar_t r_overheadsprites_pushback;
4796 static void R_View_UpdateEntityLighting (void)
4799 entity_render_t *ent;
4800 vec3_t tempdiffusenormal, avg;
4801 vec_t f, fa, fd, fdd;
4802 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4804 for (i = 0;i < r_refdef.scene.numentities;i++)
4806 ent = r_refdef.scene.entities[i];
4808 // skip unseen models and models that updated by CSQC
4809 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4813 if (ent->model && ent->model->brush.num_leafs)
4815 // TODO: use modellight for r_ambient settings on world?
4816 VectorSet(ent->modellight_ambient, 0, 0, 0);
4817 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4818 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4822 // fetch the lighting from the worldmodel data
4823 VectorClear(ent->modellight_ambient);
4824 VectorClear(ent->modellight_diffuse);
4825 VectorClear(tempdiffusenormal);
4826 if (ent->flags & RENDER_LIGHT)
4829 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4831 // complete lightning for lit sprites
4832 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4833 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4835 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4836 org[2] = org[2] + r_overheadsprites_pushback.value;
4837 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4840 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4842 if(ent->flags & RENDER_EQUALIZE)
4844 // first fix up ambient lighting...
4845 if(r_equalize_entities_minambient.value > 0)
4847 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4850 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4851 if(fa < r_equalize_entities_minambient.value * fd)
4854 // fa'/fd' = minambient
4855 // fa'+0.25*fd' = fa+0.25*fd
4857 // fa' = fd' * minambient
4858 // fd'*(0.25+minambient) = fa+0.25*fd
4860 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4861 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4863 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4864 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
4865 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4866 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4871 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4873 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4874 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4878 // adjust brightness and saturation to target
4879 avg[0] = avg[1] = avg[2] = fa / f;
4880 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4881 avg[0] = avg[1] = avg[2] = fd / f;
4882 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4888 VectorSet(ent->modellight_ambient, 1, 1, 1);
4890 // move the light direction into modelspace coordinates for lighting code
4891 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4892 if(VectorLength2(ent->modellight_lightdir) == 0)
4893 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4894 VectorNormalize(ent->modellight_lightdir);
4898 #define MAX_LINEOFSIGHTTRACES 64
4900 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4903 vec3_t boxmins, boxmaxs;
4906 dp_model_t *model = r_refdef.scene.worldmodel;
4908 if (!model || !model->brush.TraceLineOfSight)
4911 // expand the box a little
4912 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4913 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4914 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4915 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4916 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4917 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4919 // return true if eye is inside enlarged box
4920 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4924 VectorCopy(eye, start);
4925 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4926 if (model->brush.TraceLineOfSight(model, start, end))
4929 // try various random positions
4930 for (i = 0;i < numsamples;i++)
4932 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4933 if (model->brush.TraceLineOfSight(model, start, end))
4941 static void R_View_UpdateEntityVisible (void)
4946 entity_render_t *ent;
4948 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4949 : r_waterstate.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4950 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4951 : RENDER_EXTERIORMODEL;
4952 if (!r_drawviewmodel.integer)
4953 renderimask |= RENDER_VIEWMODEL;
4954 if (!r_drawexteriormodel.integer)
4955 renderimask |= RENDER_EXTERIORMODEL;
4956 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4958 // worldmodel can check visibility
4959 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4960 for (i = 0;i < r_refdef.scene.numentities;i++)
4962 ent = r_refdef.scene.entities[i];
4963 if (!(ent->flags & renderimask))
4964 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)))
4965 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4966 r_refdef.viewcache.entityvisible[i] = true;
4971 // no worldmodel or it can't check visibility
4972 for (i = 0;i < r_refdef.scene.numentities;i++)
4974 ent = r_refdef.scene.entities[i];
4975 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));
4978 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4979 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4981 for (i = 0;i < r_refdef.scene.numentities;i++)
4983 if (!r_refdef.viewcache.entityvisible[i])
4985 ent = r_refdef.scene.entities[i];
4986 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4988 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4990 continue; // temp entities do pvs only
4991 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4992 ent->last_trace_visibility = realtime;
4993 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4994 r_refdef.viewcache.entityvisible[i] = 0;
5000 /// only used if skyrendermasked, and normally returns false
5001 int R_DrawBrushModelsSky (void)
5004 entity_render_t *ent;
5007 for (i = 0;i < r_refdef.scene.numentities;i++)
5009 if (!r_refdef.viewcache.entityvisible[i])
5011 ent = r_refdef.scene.entities[i];
5012 if (!ent->model || !ent->model->DrawSky)
5014 ent->model->DrawSky(ent);
5020 static void R_DrawNoModel(entity_render_t *ent);
5021 static void R_DrawModels(void)
5024 entity_render_t *ent;
5026 for (i = 0;i < r_refdef.scene.numentities;i++)
5028 if (!r_refdef.viewcache.entityvisible[i])
5030 ent = r_refdef.scene.entities[i];
5031 r_refdef.stats.entities++;
5033 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5036 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5037 Con_Printf("R_DrawModels\n");
5038 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]);
5039 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);
5040 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);
5043 if (ent->model && ent->model->Draw != NULL)
5044 ent->model->Draw(ent);
5050 static void R_DrawModelsDepth(void)
5053 entity_render_t *ent;
5055 for (i = 0;i < r_refdef.scene.numentities;i++)
5057 if (!r_refdef.viewcache.entityvisible[i])
5059 ent = r_refdef.scene.entities[i];
5060 if (ent->model && ent->model->DrawDepth != NULL)
5061 ent->model->DrawDepth(ent);
5065 static void R_DrawModelsDebug(void)
5068 entity_render_t *ent;
5070 for (i = 0;i < r_refdef.scene.numentities;i++)
5072 if (!r_refdef.viewcache.entityvisible[i])
5074 ent = r_refdef.scene.entities[i];
5075 if (ent->model && ent->model->DrawDebug != NULL)
5076 ent->model->DrawDebug(ent);
5080 static void R_DrawModelsAddWaterPlanes(void)
5083 entity_render_t *ent;
5085 for (i = 0;i < r_refdef.scene.numentities;i++)
5087 if (!r_refdef.viewcache.entityvisible[i])
5089 ent = r_refdef.scene.entities[i];
5090 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5091 ent->model->DrawAddWaterPlanes(ent);
5095 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5097 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5099 if (r_hdr_irisadaptation.integer)
5104 vec3_t diffusenormal;
5106 vec_t brightness = 0.0f;
5111 VectorCopy(r_refdef.view.forward, forward);
5112 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5114 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5115 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5116 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5117 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5118 d = DotProduct(forward, diffusenormal);
5119 brightness += VectorLength(ambient);
5121 brightness += d * VectorLength(diffuse);
5123 brightness *= 1.0f / c;
5124 brightness += 0.00001f; // make sure it's never zero
5125 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5126 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5127 current = r_hdr_irisadaptation_value.value;
5129 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5130 else if (current > goal)
5131 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5132 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5133 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5135 else if (r_hdr_irisadaptation_value.value != 1.0f)
5136 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5139 static void R_View_SetFrustum(const int *scissor)
5142 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5143 vec3_t forward, left, up, origin, v;
5147 // flipped x coordinates (because x points left here)
5148 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5149 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5151 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5152 switch(vid.renderpath)
5154 case RENDERPATH_D3D9:
5155 case RENDERPATH_D3D10:
5156 case RENDERPATH_D3D11:
5157 // non-flipped y coordinates
5158 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5159 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5161 case RENDERPATH_SOFT:
5162 case RENDERPATH_GL11:
5163 case RENDERPATH_GL13:
5164 case RENDERPATH_GL20:
5165 case RENDERPATH_GLES1:
5166 case RENDERPATH_GLES2:
5167 // non-flipped y coordinates
5168 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5169 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5174 // we can't trust r_refdef.view.forward and friends in reflected scenes
5175 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5178 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5179 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5180 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5181 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5182 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5183 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5184 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5185 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5186 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5187 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5188 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5189 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5193 zNear = r_refdef.nearclip;
5194 nudge = 1.0 - 1.0 / (1<<23);
5195 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5196 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5197 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5198 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5199 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5200 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5201 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5202 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5208 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5209 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5210 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5211 r_refdef.view.frustum[0].dist = m[15] - m[12];
5213 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5214 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5215 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5216 r_refdef.view.frustum[1].dist = m[15] + m[12];
5218 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5219 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5220 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5221 r_refdef.view.frustum[2].dist = m[15] - m[13];
5223 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5224 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5225 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5226 r_refdef.view.frustum[3].dist = m[15] + m[13];
5228 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5229 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5230 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5231 r_refdef.view.frustum[4].dist = m[15] - m[14];
5233 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5234 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5235 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5236 r_refdef.view.frustum[5].dist = m[15] + m[14];
5239 if (r_refdef.view.useperspective)
5241 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5242 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]);
5243 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]);
5244 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]);
5245 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]);
5247 // then the normals from the corners relative to origin
5248 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5249 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5250 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5251 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5253 // in a NORMAL view, forward cross left == up
5254 // in a REFLECTED view, forward cross left == down
5255 // so our cross products above need to be adjusted for a left handed coordinate system
5256 CrossProduct(forward, left, v);
5257 if(DotProduct(v, up) < 0)
5259 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5260 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5261 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5262 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5265 // Leaving those out was a mistake, those were in the old code, and they
5266 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5267 // I couldn't reproduce it after adding those normalizations. --blub
5268 VectorNormalize(r_refdef.view.frustum[0].normal);
5269 VectorNormalize(r_refdef.view.frustum[1].normal);
5270 VectorNormalize(r_refdef.view.frustum[2].normal);
5271 VectorNormalize(r_refdef.view.frustum[3].normal);
5273 // make the corners absolute
5274 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5275 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5276 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5277 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5280 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5282 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5283 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5284 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5285 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5286 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5290 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5291 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5292 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5293 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5294 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5295 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5296 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5297 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5298 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5299 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5301 r_refdef.view.numfrustumplanes = 5;
5303 if (r_refdef.view.useclipplane)
5305 r_refdef.view.numfrustumplanes = 6;
5306 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5309 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5310 PlaneClassify(r_refdef.view.frustum + i);
5312 // LordHavoc: note to all quake engine coders, Quake had a special case
5313 // for 90 degrees which assumed a square view (wrong), so I removed it,
5314 // Quake2 has it disabled as well.
5316 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5317 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5318 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5319 //PlaneClassify(&frustum[0]);
5321 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5322 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5323 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5324 //PlaneClassify(&frustum[1]);
5326 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5327 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5328 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5329 //PlaneClassify(&frustum[2]);
5331 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5332 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5333 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5334 //PlaneClassify(&frustum[3]);
5337 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5338 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5339 //PlaneClassify(&frustum[4]);
5342 void R_View_UpdateWithScissor(const int *myscissor)
5344 R_Main_ResizeViewCache();
5345 R_View_SetFrustum(myscissor);
5346 R_View_WorldVisibility(r_refdef.view.useclipplane);
5347 R_View_UpdateEntityVisible();
5348 R_View_UpdateEntityLighting();
5349 R_AnimCache_CacheVisibleEntities();
5352 void R_View_Update(void)
5354 R_Main_ResizeViewCache();
5355 R_View_SetFrustum(NULL);
5356 R_View_WorldVisibility(r_refdef.view.useclipplane);
5357 R_View_UpdateEntityVisible();
5358 R_View_UpdateEntityLighting();
5359 R_AnimCache_CacheVisibleEntities();
5362 float viewscalefpsadjusted = 1.0f;
5364 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5366 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5367 scale = bound(0.03125f, scale, 1.0f);
5368 *outwidth = (int)ceil(width * scale);
5369 *outheight = (int)ceil(height * scale);
5372 void R_Mesh_SetMainRenderTargets(void)
5374 if (r_bloomstate.fbo_framebuffer)
5375 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5377 R_Mesh_ResetRenderTargets();
5380 void R_SetupView(qboolean allowwaterclippingplane)
5382 const float *customclipplane = NULL;
5384 int scaledwidth, scaledheight;
5385 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5387 // LordHavoc: couldn't figure out how to make this approach the
5388 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5389 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5390 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5391 dist = r_refdef.view.clipplane.dist;
5392 plane[0] = r_refdef.view.clipplane.normal[0];
5393 plane[1] = r_refdef.view.clipplane.normal[1];
5394 plane[2] = r_refdef.view.clipplane.normal[2];
5396 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5399 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5400 if (!r_refdef.view.useperspective)
5401 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);
5402 else if (vid.stencil && r_useinfinitefarclip.integer)
5403 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);
5405 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);
5406 R_Mesh_SetMainRenderTargets();
5407 R_SetViewport(&r_refdef.view.viewport);
5408 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5410 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5411 float screenplane[4];
5412 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5413 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5414 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5415 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5416 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5420 void R_EntityMatrix(const matrix4x4_t *matrix)
5422 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5424 gl_modelmatrixchanged = false;
5425 gl_modelmatrix = *matrix;
5426 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5427 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5428 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5429 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5431 switch(vid.renderpath)
5433 case RENDERPATH_D3D9:
5435 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5436 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5439 case RENDERPATH_D3D10:
5440 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5442 case RENDERPATH_D3D11:
5443 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5445 case RENDERPATH_GL11:
5446 case RENDERPATH_GL13:
5447 case RENDERPATH_GLES1:
5448 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5450 case RENDERPATH_SOFT:
5451 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5452 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5454 case RENDERPATH_GL20:
5455 case RENDERPATH_GLES2:
5456 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5457 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5463 void R_ResetViewRendering2D(void)
5465 r_viewport_t viewport;
5468 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5469 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);
5470 R_Mesh_ResetRenderTargets();
5471 R_SetViewport(&viewport);
5472 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5473 GL_Color(1, 1, 1, 1);
5474 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5475 GL_BlendFunc(GL_ONE, GL_ZERO);
5476 GL_ScissorTest(false);
5477 GL_DepthMask(false);
5478 GL_DepthRange(0, 1);
5479 GL_DepthTest(false);
5480 GL_DepthFunc(GL_LEQUAL);
5481 R_EntityMatrix(&identitymatrix);
5482 R_Mesh_ResetTextureState();
5483 GL_PolygonOffset(0, 0);
5484 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5485 switch(vid.renderpath)
5487 case RENDERPATH_GL11:
5488 case RENDERPATH_GL13:
5489 case RENDERPATH_GL20:
5490 case RENDERPATH_GLES1:
5491 case RENDERPATH_GLES2:
5492 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5494 case RENDERPATH_D3D9:
5495 case RENDERPATH_D3D10:
5496 case RENDERPATH_D3D11:
5497 case RENDERPATH_SOFT:
5500 GL_CullFace(GL_NONE);
5503 void R_ResetViewRendering3D(void)
5508 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5509 GL_Color(1, 1, 1, 1);
5510 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5511 GL_BlendFunc(GL_ONE, GL_ZERO);
5512 GL_ScissorTest(true);
5514 GL_DepthRange(0, 1);
5516 GL_DepthFunc(GL_LEQUAL);
5517 R_EntityMatrix(&identitymatrix);
5518 R_Mesh_ResetTextureState();
5519 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5520 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5521 switch(vid.renderpath)
5523 case RENDERPATH_GL11:
5524 case RENDERPATH_GL13:
5525 case RENDERPATH_GL20:
5526 case RENDERPATH_GLES1:
5527 case RENDERPATH_GLES2:
5528 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5530 case RENDERPATH_D3D9:
5531 case RENDERPATH_D3D10:
5532 case RENDERPATH_D3D11:
5533 case RENDERPATH_SOFT:
5536 GL_CullFace(r_refdef.view.cullface_back);
5541 R_RenderView_UpdateViewVectors
5544 static void R_RenderView_UpdateViewVectors(void)
5546 // break apart the view matrix into vectors for various purposes
5547 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5548 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5549 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5550 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5551 // make an inverted copy of the view matrix for tracking sprites
5552 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5555 void R_RenderScene(void);
5556 void R_RenderWaterPlanes(void);
5558 static void R_Water_StartFrame(void)
5561 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5562 r_waterstate_waterplane_t *p;
5564 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5567 switch(vid.renderpath)
5569 case RENDERPATH_GL20:
5570 case RENDERPATH_D3D9:
5571 case RENDERPATH_D3D10:
5572 case RENDERPATH_D3D11:
5573 case RENDERPATH_SOFT:
5574 case RENDERPATH_GLES2:
5576 case RENDERPATH_GL11:
5577 case RENDERPATH_GL13:
5578 case RENDERPATH_GLES1:
5582 // set waterwidth and waterheight to the water resolution that will be
5583 // used (often less than the screen resolution for faster rendering)
5584 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5586 // calculate desired texture sizes
5587 // can't use water if the card does not support the texture size
5588 if (!r_water.integer || r_showsurfaces.integer)
5589 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5590 else if (vid.support.arb_texture_non_power_of_two)
5592 texturewidth = waterwidth;
5593 textureheight = waterheight;
5594 camerawidth = waterwidth;
5595 cameraheight = waterheight;
5599 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5600 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5601 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5602 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5605 // allocate textures as needed
5606 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5608 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5609 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5611 if (p->texture_refraction)
5612 R_FreeTexture(p->texture_refraction);
5613 p->texture_refraction = NULL;
5614 if (p->texture_reflection)
5615 R_FreeTexture(p->texture_reflection);
5616 p->texture_reflection = NULL;
5617 if (p->texture_camera)
5618 R_FreeTexture(p->texture_camera);
5619 p->texture_camera = NULL;
5621 memset(&r_waterstate, 0, sizeof(r_waterstate));
5622 r_waterstate.texturewidth = texturewidth;
5623 r_waterstate.textureheight = textureheight;
5624 r_waterstate.camerawidth = camerawidth;
5625 r_waterstate.cameraheight = cameraheight;
5628 if (r_waterstate.texturewidth)
5630 int scaledwidth, scaledheight;
5632 r_waterstate.enabled = true;
5634 // when doing a reduced render (HDR) we want to use a smaller area
5635 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5636 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5637 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5639 // set up variables that will be used in shader setup
5640 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5641 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5642 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5643 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5646 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5647 r_waterstate.numwaterplanes = 0;
5650 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5652 int planeindex, bestplaneindex, vertexindex;
5653 vec3_t mins, maxs, normal, center, v, n;
5654 vec_t planescore, bestplanescore;
5656 r_waterstate_waterplane_t *p;
5657 texture_t *t = R_GetCurrentTexture(surface->texture);
5659 rsurface.texture = t;
5660 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5661 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5662 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5664 // average the vertex normals, find the surface bounds (after deformvertexes)
5665 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5666 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5667 VectorCopy(n, normal);
5668 VectorCopy(v, mins);
5669 VectorCopy(v, maxs);
5670 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5672 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5673 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5674 VectorAdd(normal, n, normal);
5675 mins[0] = min(mins[0], v[0]);
5676 mins[1] = min(mins[1], v[1]);
5677 mins[2] = min(mins[2], v[2]);
5678 maxs[0] = max(maxs[0], v[0]);
5679 maxs[1] = max(maxs[1], v[1]);
5680 maxs[2] = max(maxs[2], v[2]);
5682 VectorNormalize(normal);
5683 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5685 VectorCopy(normal, plane.normal);
5686 VectorNormalize(plane.normal);
5687 plane.dist = DotProduct(center, plane.normal);
5688 PlaneClassify(&plane);
5689 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5691 // skip backfaces (except if nocullface is set)
5692 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5694 VectorNegate(plane.normal, plane.normal);
5696 PlaneClassify(&plane);
5700 // find a matching plane if there is one
5701 bestplaneindex = -1;
5702 bestplanescore = 1048576.0f;
5703 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5705 if(p->camera_entity == t->camera_entity)
5707 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5708 if (bestplaneindex < 0 || bestplanescore > planescore)
5710 bestplaneindex = planeindex;
5711 bestplanescore = planescore;
5715 planeindex = bestplaneindex;
5716 p = r_waterstate.waterplanes + planeindex;
5718 // if this surface does not fit any known plane rendered this frame, add one
5719 if ((planeindex < 0 || bestplanescore > 0.001f) && r_waterstate.numwaterplanes < r_waterstate.maxwaterplanes)
5721 // store the new plane
5722 planeindex = r_waterstate.numwaterplanes++;
5723 p = r_waterstate.waterplanes + planeindex;
5725 // clear materialflags and pvs
5726 p->materialflags = 0;
5727 p->pvsvalid = false;
5728 p->camera_entity = t->camera_entity;
5729 VectorCopy(mins, p->mins);
5730 VectorCopy(maxs, p->maxs);
5734 // merge mins/maxs when we're adding this surface to the plane
5735 p->mins[0] = min(p->mins[0], mins[0]);
5736 p->mins[1] = min(p->mins[1], mins[1]);
5737 p->mins[2] = min(p->mins[2], mins[2]);
5738 p->maxs[0] = max(p->maxs[0], maxs[0]);
5739 p->maxs[1] = max(p->maxs[1], maxs[1]);
5740 p->maxs[2] = max(p->maxs[2], maxs[2]);
5742 // merge this surface's materialflags into the waterplane
5743 p->materialflags |= t->currentmaterialflags;
5744 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5746 // merge this surface's PVS into the waterplane
5747 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5748 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5750 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5756 extern cvar_t r_drawparticles;
5757 extern cvar_t r_drawdecals;
5759 static void R_Water_ProcessPlanes(void)
5762 r_refdef_view_t originalview;
5763 r_refdef_view_t myview;
5764 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;
5765 r_waterstate_waterplane_t *p;
5768 originalview = r_refdef.view;
5770 // lowquality hack, temporarily shut down some cvars and restore afterwards
5771 qualityreduction = r_water_lowquality.integer;
5772 if (qualityreduction > 0)
5774 if (qualityreduction >= 1)
5776 old_r_shadows = r_shadows.integer;
5777 old_r_worldrtlight = r_shadow_realtime_world.integer;
5778 old_r_dlight = r_shadow_realtime_dlight.integer;
5779 Cvar_SetValueQuick(&r_shadows, 0);
5780 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5781 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5783 if (qualityreduction >= 2)
5785 old_r_dynamic = r_dynamic.integer;
5786 old_r_particles = r_drawparticles.integer;
5787 old_r_decals = r_drawdecals.integer;
5788 Cvar_SetValueQuick(&r_dynamic, 0);
5789 Cvar_SetValueQuick(&r_drawparticles, 0);
5790 Cvar_SetValueQuick(&r_drawdecals, 0);
5794 // make sure enough textures are allocated
5795 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5797 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5799 if (!p->texture_refraction)
5800 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);
5801 if (!p->texture_refraction)
5804 else if (p->materialflags & MATERIALFLAG_CAMERA)
5806 if (!p->texture_camera)
5807 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);
5808 if (!p->texture_camera)
5812 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5814 if (!p->texture_reflection)
5815 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);
5816 if (!p->texture_reflection)
5822 r_refdef.view = originalview;
5823 r_refdef.view.showdebug = false;
5824 r_refdef.view.width = r_waterstate.waterwidth;
5825 r_refdef.view.height = r_waterstate.waterheight;
5826 r_refdef.view.useclipplane = true;
5827 myview = r_refdef.view;
5828 r_waterstate.renderingscene = true;
5829 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5831 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5833 r_refdef.view = myview;
5834 if(r_water_scissormode.integer)
5837 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5838 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5841 // render reflected scene and copy into texture
5842 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5843 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5844 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5845 r_refdef.view.clipplane = p->plane;
5846 // reverse the cullface settings for this render
5847 r_refdef.view.cullface_front = GL_FRONT;
5848 r_refdef.view.cullface_back = GL_BACK;
5849 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5851 r_refdef.view.usecustompvs = true;
5853 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5855 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5858 r_waterstate.hideplayer = r_water_hideplayer.integer >= 2;
5859 R_ResetViewRendering3D();
5860 R_ClearScreen(r_refdef.fogenabled);
5861 if(r_water_scissormode.integer & 2)
5862 R_View_UpdateWithScissor(myscissor);
5865 if(r_water_scissormode.integer & 1)
5866 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5869 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);
5870 r_waterstate.hideplayer = false;
5873 // render the normal view scene and copy into texture
5874 // (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)
5875 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5877 r_refdef.view = myview;
5878 if(r_water_scissormode.integer)
5881 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5882 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5885 r_waterstate.hideplayer = r_water_hideplayer.integer >= 1;
5887 r_refdef.view.clipplane = p->plane;
5888 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5889 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5891 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5893 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5894 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5895 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5896 R_RenderView_UpdateViewVectors();
5897 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5899 r_refdef.view.usecustompvs = true;
5900 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);
5904 PlaneClassify(&r_refdef.view.clipplane);
5906 R_ResetViewRendering3D();
5907 R_ClearScreen(r_refdef.fogenabled);
5908 if(r_water_scissormode.integer & 2)
5909 R_View_UpdateWithScissor(myscissor);
5912 if(r_water_scissormode.integer & 1)
5913 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5916 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);
5917 r_waterstate.hideplayer = false;
5919 else if (p->materialflags & MATERIALFLAG_CAMERA)
5921 r_refdef.view = myview;
5923 r_refdef.view.clipplane = p->plane;
5924 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5925 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5927 r_refdef.view.width = r_waterstate.camerawidth;
5928 r_refdef.view.height = r_waterstate.cameraheight;
5929 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5930 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5931 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5932 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5934 if(p->camera_entity)
5936 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5937 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5940 // note: all of the view is used for displaying... so
5941 // there is no use in scissoring
5943 // reverse the cullface settings for this render
5944 r_refdef.view.cullface_front = GL_FRONT;
5945 r_refdef.view.cullface_back = GL_BACK;
5946 // also reverse the view matrix
5947 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
5948 R_RenderView_UpdateViewVectors();
5949 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5951 r_refdef.view.usecustompvs = true;
5952 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);
5955 // camera needs no clipplane
5956 r_refdef.view.useclipplane = false;
5958 PlaneClassify(&r_refdef.view.clipplane);
5960 r_waterstate.hideplayer = false;
5962 R_ResetViewRendering3D();
5963 R_ClearScreen(r_refdef.fogenabled);
5967 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);
5968 r_waterstate.hideplayer = false;
5972 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5973 r_waterstate.renderingscene = false;
5974 r_refdef.view = originalview;
5975 R_ResetViewRendering3D();
5976 R_ClearScreen(r_refdef.fogenabled);
5980 r_refdef.view = originalview;
5981 r_waterstate.renderingscene = false;
5982 Cvar_SetValueQuick(&r_water, 0);
5983 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5985 // lowquality hack, restore cvars
5986 if (qualityreduction > 0)
5988 if (qualityreduction >= 1)
5990 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5991 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5992 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5994 if (qualityreduction >= 2)
5996 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5997 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5998 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6003 void R_Bloom_StartFrame(void)
6005 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6006 int viewwidth, viewheight;
6009 if (r_viewscale_fpsscaling.integer)
6011 double actualframetime;
6012 double targetframetime;
6014 actualframetime = r_refdef.lastdrawscreentime;
6015 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6016 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6017 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6018 if (r_viewscale_fpsscaling_stepsize.value > 0)
6019 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6020 viewscalefpsadjusted += adjust;
6021 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6024 viewscalefpsadjusted = 1.0f;
6026 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6028 switch(vid.renderpath)
6030 case RENDERPATH_GL20:
6031 case RENDERPATH_D3D9:
6032 case RENDERPATH_D3D10:
6033 case RENDERPATH_D3D11:
6034 case RENDERPATH_SOFT:
6035 case RENDERPATH_GLES2:
6037 case RENDERPATH_GL11:
6038 case RENDERPATH_GL13:
6039 case RENDERPATH_GLES1:
6043 // set bloomwidth and bloomheight to the bloom resolution that will be
6044 // used (often less than the screen resolution for faster rendering)
6045 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6046 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6047 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6048 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6049 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6051 // calculate desired texture sizes
6052 if (vid.support.arb_texture_non_power_of_two)
6054 screentexturewidth = vid.width;
6055 screentextureheight = vid.height;
6056 bloomtexturewidth = r_bloomstate.bloomwidth;
6057 bloomtextureheight = r_bloomstate.bloomheight;
6061 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6062 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6063 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
6064 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
6067 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))
6069 Cvar_SetValueQuick(&r_hdr, 0);
6070 Cvar_SetValueQuick(&r_bloom, 0);
6071 Cvar_SetValueQuick(&r_motionblur, 0);
6072 Cvar_SetValueQuick(&r_damageblur, 0);
6075 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)
6076 screentexturewidth = screentextureheight = 0;
6077 if (!r_hdr.integer && !r_bloom.integer)
6078 bloomtexturewidth = bloomtextureheight = 0;
6080 textype = TEXTYPE_COLORBUFFER;
6081 switch (vid.renderpath)
6083 case RENDERPATH_GL20:
6084 case RENDERPATH_GLES2:
6085 if (vid.support.ext_framebuffer_object)
6087 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6088 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6091 case RENDERPATH_GL11:
6092 case RENDERPATH_GL13:
6093 case RENDERPATH_GLES1:
6094 case RENDERPATH_D3D9:
6095 case RENDERPATH_D3D10:
6096 case RENDERPATH_D3D11:
6097 case RENDERPATH_SOFT:
6101 // allocate textures as needed
6102 if (r_bloomstate.screentexturewidth != screentexturewidth
6103 || r_bloomstate.screentextureheight != screentextureheight
6104 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6105 || r_bloomstate.bloomtextureheight != bloomtextureheight
6106 || r_bloomstate.texturetype != textype
6107 || r_bloomstate.viewfbo != r_viewfbo.integer)
6109 if (r_bloomstate.texture_bloom)
6110 R_FreeTexture(r_bloomstate.texture_bloom);
6111 r_bloomstate.texture_bloom = NULL;
6112 if (r_bloomstate.texture_screen)
6113 R_FreeTexture(r_bloomstate.texture_screen);
6114 r_bloomstate.texture_screen = NULL;
6115 if (r_bloomstate.fbo_framebuffer)
6116 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6117 r_bloomstate.fbo_framebuffer = 0;
6118 if (r_bloomstate.texture_framebuffercolor)
6119 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6120 r_bloomstate.texture_framebuffercolor = NULL;
6121 if (r_bloomstate.texture_framebufferdepth)
6122 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6123 r_bloomstate.texture_framebufferdepth = NULL;
6124 r_bloomstate.screentexturewidth = screentexturewidth;
6125 r_bloomstate.screentextureheight = screentextureheight;
6126 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6127 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);
6128 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6130 // FIXME: choose depth bits based on a cvar
6131 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6132 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);
6133 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6134 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6136 // render depth into one texture and normalmap into the other
6140 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6141 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6142 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6143 if (status != GL_FRAMEBUFFER_COMPLETE)
6144 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6148 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6149 r_bloomstate.bloomtextureheight = bloomtextureheight;
6150 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6151 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);
6152 r_bloomstate.viewfbo = r_viewfbo.integer;
6153 r_bloomstate.texturetype = textype;
6156 // when doing a reduced render (HDR) we want to use a smaller area
6157 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6158 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6159 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6160 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6161 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6163 // set up a texcoord array for the full resolution screen image
6164 // (we have to keep this around to copy back during final render)
6165 r_bloomstate.screentexcoord2f[0] = 0;
6166 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6167 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6168 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
6169 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
6170 r_bloomstate.screentexcoord2f[5] = 0;
6171 r_bloomstate.screentexcoord2f[6] = 0;
6172 r_bloomstate.screentexcoord2f[7] = 0;
6174 // set up a texcoord array for the reduced resolution bloom image
6175 // (which will be additive blended over the screen image)
6176 r_bloomstate.bloomtexcoord2f[0] = 0;
6177 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6178 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6179 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6180 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6181 r_bloomstate.bloomtexcoord2f[5] = 0;
6182 r_bloomstate.bloomtexcoord2f[6] = 0;
6183 r_bloomstate.bloomtexcoord2f[7] = 0;
6185 switch(vid.renderpath)
6187 case RENDERPATH_GL11:
6188 case RENDERPATH_GL13:
6189 case RENDERPATH_GL20:
6190 case RENDERPATH_SOFT:
6191 case RENDERPATH_GLES1:
6192 case RENDERPATH_GLES2:
6194 case RENDERPATH_D3D9:
6195 case RENDERPATH_D3D10:
6196 case RENDERPATH_D3D11:
6199 for (i = 0;i < 4;i++)
6201 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6202 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6203 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6204 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6210 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6212 r_bloomstate.enabled = true;
6213 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6216 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);
6218 if (r_bloomstate.fbo_framebuffer)
6219 r_refdef.view.clear = true;
6222 void R_Bloom_CopyBloomTexture(float colorscale)
6224 r_refdef.stats.bloom++;
6226 // scale down screen texture to the bloom texture size
6228 R_Mesh_SetMainRenderTargets();
6229 R_SetViewport(&r_bloomstate.viewport);
6230 GL_BlendFunc(GL_ONE, GL_ZERO);
6231 GL_Color(colorscale, colorscale, colorscale, 1);
6232 // 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...
6233 switch(vid.renderpath)
6235 case RENDERPATH_GL11:
6236 case RENDERPATH_GL13:
6237 case RENDERPATH_GL20:
6238 case RENDERPATH_GLES1:
6239 case RENDERPATH_GLES2:
6240 case RENDERPATH_SOFT:
6241 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6243 case RENDERPATH_D3D9:
6244 case RENDERPATH_D3D10:
6245 case RENDERPATH_D3D11:
6246 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6249 // TODO: do boxfilter scale-down in shader?
6250 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6251 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6252 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6254 // we now have a bloom image in the framebuffer
6255 // copy it into the bloom image texture for later processing
6256 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);
6257 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6260 void R_Bloom_CopyHDRTexture(void)
6262 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);
6263 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6266 void R_Bloom_MakeTexture(void)
6269 float xoffset, yoffset, r, brighten;
6271 r_refdef.stats.bloom++;
6273 R_ResetViewRendering2D();
6275 // we have a bloom image in the framebuffer
6277 R_SetViewport(&r_bloomstate.viewport);
6279 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6282 r = bound(0, r_bloom_colorexponent.value / x, 1);
6283 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6285 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6286 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6287 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6288 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6290 // copy the vertically blurred bloom view to a texture
6291 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);
6292 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6295 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6296 brighten = r_bloom_brighten.value;
6297 if (r_bloomstate.hdr)
6298 brighten *= r_hdr_range.value;
6299 brighten = sqrt(brighten);
6301 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6302 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6304 for (dir = 0;dir < 2;dir++)
6306 // blend on at multiple vertical offsets to achieve a vertical blur
6307 // TODO: do offset blends using GLSL
6308 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6309 GL_BlendFunc(GL_ONE, GL_ZERO);
6310 for (x = -range;x <= range;x++)
6312 if (!dir){xoffset = 0;yoffset = x;}
6313 else {xoffset = x;yoffset = 0;}
6314 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6315 yoffset /= (float)r_bloomstate.bloomtextureheight;
6316 // compute a texcoord array with the specified x and y offset
6317 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6318 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6319 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6320 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6321 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6322 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6323 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6324 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6325 // this r value looks like a 'dot' particle, fading sharply to
6326 // black at the edges
6327 // (probably not realistic but looks good enough)
6328 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6329 //r = brighten/(range*2+1);
6330 r = brighten / (range * 2 + 1);
6332 r *= (1 - x*x/(float)(range*range));
6333 GL_Color(r, r, r, 1);
6334 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6335 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6336 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6337 GL_BlendFunc(GL_ONE, GL_ONE);
6340 // copy the vertically blurred bloom view to a texture
6341 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);
6342 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6346 void R_HDR_RenderBloomTexture(void)
6348 int oldwidth, oldheight;
6349 float oldcolorscale;
6350 qboolean oldwaterstate;
6352 oldwaterstate = r_waterstate.enabled;
6353 oldcolorscale = r_refdef.view.colorscale;
6354 oldwidth = r_refdef.view.width;
6355 oldheight = r_refdef.view.height;
6356 r_refdef.view.width = r_bloomstate.bloomwidth;
6357 r_refdef.view.height = r_bloomstate.bloomheight;
6359 if(r_hdr.integer < 2)
6360 r_waterstate.enabled = false;
6362 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6363 // TODO: add exposure compensation features
6364 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6366 r_refdef.view.showdebug = false;
6367 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6369 R_ResetViewRendering3D();
6371 R_ClearScreen(r_refdef.fogenabled);
6372 if (r_timereport_active)
6373 R_TimeReport("HDRclear");
6376 if (r_timereport_active)
6377 R_TimeReport("visibility");
6379 // only do secondary renders with HDR if r_hdr is 2 or higher
6380 r_waterstate.numwaterplanes = 0;
6381 if (r_waterstate.enabled)
6382 R_RenderWaterPlanes();
6384 r_refdef.view.showdebug = true;
6386 r_waterstate.numwaterplanes = 0;
6388 R_ResetViewRendering2D();
6390 R_Bloom_CopyHDRTexture();
6391 R_Bloom_MakeTexture();
6393 // restore the view settings
6394 r_waterstate.enabled = oldwaterstate;
6395 r_refdef.view.width = oldwidth;
6396 r_refdef.view.height = oldheight;
6397 r_refdef.view.colorscale = oldcolorscale;
6399 R_ResetViewRendering3D();
6401 R_ClearScreen(r_refdef.fogenabled);
6402 if (r_timereport_active)
6403 R_TimeReport("viewclear");
6406 static void R_BlendView(void)
6408 unsigned int permutation;
6409 float uservecs[4][4];
6411 switch (vid.renderpath)
6413 case RENDERPATH_GL20:
6414 case RENDERPATH_D3D9:
6415 case RENDERPATH_D3D10:
6416 case RENDERPATH_D3D11:
6417 case RENDERPATH_SOFT:
6418 case RENDERPATH_GLES2:
6420 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6421 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6422 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6423 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6424 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6426 if (r_bloomstate.texture_screen)
6428 // make sure the buffer is available
6429 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6431 R_ResetViewRendering2D();
6432 R_Mesh_SetMainRenderTargets();
6434 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6436 // declare variables
6437 float blur_factor, blur_mouseaccel, blur_velocity;
6438 static float blur_average;
6439 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6441 // set a goal for the factoring
6442 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6443 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6444 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6445 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6446 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6447 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6449 // from the goal, pick an averaged value between goal and last value
6450 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6451 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6453 // enforce minimum amount of blur
6454 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6456 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6458 // calculate values into a standard alpha
6459 cl.motionbluralpha = 1 - exp(-
6461 (r_motionblur.value * blur_factor / 80)
6463 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6466 max(0.0001, cl.time - cl.oldtime) // fps independent
6469 // randomization for the blur value to combat persistent ghosting
6470 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6471 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6474 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6476 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6477 GL_Color(1, 1, 1, cl.motionbluralpha);
6478 switch(vid.renderpath)
6480 case RENDERPATH_GL11:
6481 case RENDERPATH_GL13:
6482 case RENDERPATH_GL20:
6483 case RENDERPATH_GLES1:
6484 case RENDERPATH_GLES2:
6485 case RENDERPATH_SOFT:
6486 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6488 case RENDERPATH_D3D9:
6489 case RENDERPATH_D3D10:
6490 case RENDERPATH_D3D11:
6491 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6494 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6495 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6496 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6499 // updates old view angles for next pass
6500 VectorCopy(cl.viewangles, blur_oldangles);
6503 // copy view into the screen texture
6504 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);
6505 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6507 else if (!r_bloomstate.texture_bloom)
6509 // we may still have to do view tint...
6510 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6512 // apply a color tint to the whole view
6513 R_ResetViewRendering2D();
6514 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6515 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6516 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6517 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6518 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6520 break; // no screen processing, no bloom, skip it
6523 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6525 // render simple bloom effect
6526 // copy the screen and shrink it and darken it for the bloom process
6527 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6528 // make the bloom texture
6529 R_Bloom_MakeTexture();
6532 #if _MSC_VER >= 1400
6533 #define sscanf sscanf_s
6535 memset(uservecs, 0, sizeof(uservecs));
6536 if (r_glsl_postprocess_uservec1_enable.integer)
6537 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6538 if (r_glsl_postprocess_uservec2_enable.integer)
6539 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6540 if (r_glsl_postprocess_uservec3_enable.integer)
6541 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6542 if (r_glsl_postprocess_uservec4_enable.integer)
6543 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6545 R_ResetViewRendering2D();
6546 GL_Color(1, 1, 1, 1);
6547 GL_BlendFunc(GL_ONE, GL_ZERO);
6549 switch(vid.renderpath)
6551 case RENDERPATH_GL20:
6552 case RENDERPATH_GLES2:
6553 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6554 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6555 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6556 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6557 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6558 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]);
6559 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6560 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]);
6561 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]);
6562 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]);
6563 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]);
6564 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6565 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6566 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);
6568 case RENDERPATH_D3D9:
6570 // 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...
6571 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6572 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6573 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6574 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6575 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6576 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6577 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6578 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6579 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6580 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6581 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6582 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6583 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6584 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6587 case RENDERPATH_D3D10:
6588 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6590 case RENDERPATH_D3D11:
6591 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6593 case RENDERPATH_SOFT:
6594 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6595 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6596 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6597 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6598 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6599 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6600 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6601 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6602 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6603 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6604 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6605 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6606 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6607 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6612 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6613 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6615 case RENDERPATH_GL11:
6616 case RENDERPATH_GL13:
6617 case RENDERPATH_GLES1:
6618 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6620 // apply a color tint to the whole view
6621 R_ResetViewRendering2D();
6622 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6623 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6624 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6625 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6626 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6632 matrix4x4_t r_waterscrollmatrix;
6634 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6637 if (gamemode == GAME_NEHAHRA)
6639 if (gl_fogenable.integer)
6641 r_refdef.oldgl_fogenable = true;
6642 r_refdef.fog_density = gl_fogdensity.value;
6643 r_refdef.fog_red = gl_fogred.value;
6644 r_refdef.fog_green = gl_foggreen.value;
6645 r_refdef.fog_blue = gl_fogblue.value;
6646 r_refdef.fog_alpha = 1;
6647 r_refdef.fog_start = 0;
6648 r_refdef.fog_end = gl_skyclip.value;
6649 r_refdef.fog_height = 1<<30;
6650 r_refdef.fog_fadedepth = 128;
6652 else if (r_refdef.oldgl_fogenable)
6654 r_refdef.oldgl_fogenable = false;
6655 r_refdef.fog_density = 0;
6656 r_refdef.fog_red = 0;
6657 r_refdef.fog_green = 0;
6658 r_refdef.fog_blue = 0;
6659 r_refdef.fog_alpha = 0;
6660 r_refdef.fog_start = 0;
6661 r_refdef.fog_end = 0;
6662 r_refdef.fog_height = 1<<30;
6663 r_refdef.fog_fadedepth = 128;
6668 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6669 r_refdef.fog_start = max(0, r_refdef.fog_start);
6670 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6672 if (r_refdef.fog_density && r_drawfog.integer)
6674 r_refdef.fogenabled = true;
6675 // this is the point where the fog reaches 0.9986 alpha, which we
6676 // consider a good enough cutoff point for the texture
6677 // (0.9986 * 256 == 255.6)
6678 if (r_fog_exp2.integer)
6679 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6681 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6682 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6683 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6684 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6685 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6686 R_BuildFogHeightTexture();
6687 // fog color was already set
6688 // update the fog texture
6689 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)
6690 R_BuildFogTexture();
6691 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6692 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6695 r_refdef.fogenabled = false;
6698 if (r_refdef.fog_density)
6700 r_refdef.fogcolor[0] = r_refdef.fog_red;
6701 r_refdef.fogcolor[1] = r_refdef.fog_green;
6702 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6704 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6705 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6706 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6707 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6711 VectorCopy(r_refdef.fogcolor, fogvec);
6712 // color.rgb *= ContrastBoost * SceneBrightness;
6713 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6714 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6715 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6716 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6721 void R_UpdateVariables(void)
6725 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6727 r_refdef.farclip = r_farclip_base.value;
6728 if (r_refdef.scene.worldmodel)
6729 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6730 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6732 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6733 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6734 r_refdef.polygonfactor = 0;
6735 r_refdef.polygonoffset = 0;
6736 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6737 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6739 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6740 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6741 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6742 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6743 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6744 if (FAKELIGHT_ENABLED)
6746 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6748 if (r_showsurfaces.integer)
6750 r_refdef.scene.rtworld = false;
6751 r_refdef.scene.rtworldshadows = false;
6752 r_refdef.scene.rtdlight = false;
6753 r_refdef.scene.rtdlightshadows = false;
6754 r_refdef.lightmapintensity = 0;
6757 switch(vid.renderpath)
6759 case RENDERPATH_GL20:
6760 case RENDERPATH_D3D9:
6761 case RENDERPATH_D3D10:
6762 case RENDERPATH_D3D11:
6763 case RENDERPATH_SOFT:
6764 case RENDERPATH_GLES2:
6765 if(v_glslgamma.integer && !vid_gammatables_trivial)
6767 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6769 // build GLSL gamma texture
6770 #define RAMPWIDTH 256
6771 unsigned short ramp[RAMPWIDTH * 3];
6772 unsigned char rampbgr[RAMPWIDTH][4];
6775 r_texture_gammaramps_serial = vid_gammatables_serial;
6777 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6778 for(i = 0; i < RAMPWIDTH; ++i)
6780 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6781 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6782 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6785 if (r_texture_gammaramps)
6787 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6791 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6797 // remove GLSL gamma texture
6800 case RENDERPATH_GL11:
6801 case RENDERPATH_GL13:
6802 case RENDERPATH_GLES1:
6807 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6808 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6814 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6815 if( scenetype != r_currentscenetype ) {
6816 // store the old scenetype
6817 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6818 r_currentscenetype = scenetype;
6819 // move in the new scene
6820 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6829 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6831 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6832 if( scenetype == r_currentscenetype ) {
6833 return &r_refdef.scene;
6835 return &r_scenes_store[ scenetype ];
6839 int R_SortEntities_Compare(const void *ap, const void *bp)
6841 const entity_render_t *a = *(const entity_render_t **)ap;
6842 const entity_render_t *b = *(const entity_render_t **)bp;
6845 if(a->model < b->model)
6847 if(a->model > b->model)
6851 // TODO possibly calculate the REAL skinnum here first using
6853 if(a->skinnum < b->skinnum)
6855 if(a->skinnum > b->skinnum)
6858 // everything we compared is equal
6861 void R_SortEntities(void)
6863 // below or equal 2 ents, sorting never gains anything
6864 if(r_refdef.scene.numentities <= 2)
6867 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6875 int dpsoftrast_test;
6876 extern void R_Shadow_UpdateBounceGridTexture(void);
6877 extern cvar_t r_shadow_bouncegrid;
6878 void R_RenderView(void)
6880 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6882 dpsoftrast_test = r_test.integer;
6884 if (r_timereport_active)
6885 R_TimeReport("start");
6886 r_textureframe++; // used only by R_GetCurrentTexture
6887 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6889 if(R_CompileShader_CheckStaticParms())
6892 if (!r_drawentities.integer)
6893 r_refdef.scene.numentities = 0;
6894 else if (r_sortentities.integer)
6897 R_AnimCache_ClearCache();
6898 R_FrameData_NewFrame();
6900 /* adjust for stereo display */
6901 if(R_Stereo_Active())
6903 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);
6904 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6907 if (r_refdef.view.isoverlay)
6909 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6910 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6911 R_TimeReport("depthclear");
6913 r_refdef.view.showdebug = false;
6915 r_waterstate.enabled = false;
6916 r_waterstate.numwaterplanes = 0;
6920 r_refdef.view.matrix = originalmatrix;
6926 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6928 r_refdef.view.matrix = originalmatrix;
6929 return; //Host_Error ("R_RenderView: NULL worldmodel");
6932 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6934 R_RenderView_UpdateViewVectors();
6936 R_Shadow_UpdateWorldLightSelection();
6938 R_Bloom_StartFrame();
6939 R_Water_StartFrame();
6942 if (r_timereport_active)
6943 R_TimeReport("viewsetup");
6945 R_ResetViewRendering3D();
6947 if (r_refdef.view.clear || r_refdef.fogenabled)
6949 R_ClearScreen(r_refdef.fogenabled);
6950 if (r_timereport_active)
6951 R_TimeReport("viewclear");
6953 r_refdef.view.clear = true;
6955 // this produces a bloom texture to be used in R_BlendView() later
6956 if (r_bloomstate.hdr)
6958 R_HDR_RenderBloomTexture();
6959 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6960 r_textureframe++; // used only by R_GetCurrentTexture
6963 r_refdef.view.showdebug = true;
6966 if (r_timereport_active)
6967 R_TimeReport("visibility");
6969 R_Shadow_UpdateBounceGridTexture();
6970 if (r_timereport_active && r_shadow_bouncegrid.integer)
6971 R_TimeReport("bouncegrid");
6973 r_waterstate.numwaterplanes = 0;
6974 if (r_waterstate.enabled)
6975 R_RenderWaterPlanes();
6978 r_waterstate.numwaterplanes = 0;
6981 if (r_timereport_active)
6982 R_TimeReport("blendview");
6984 GL_Scissor(0, 0, vid.width, vid.height);
6985 GL_ScissorTest(false);
6987 r_refdef.view.matrix = originalmatrix;
6992 void R_RenderWaterPlanes(void)
6994 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6996 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6997 if (r_timereport_active)
6998 R_TimeReport("waterworld");
7001 // don't let sound skip if going slow
7002 if (r_refdef.scene.extraupdate)
7005 R_DrawModelsAddWaterPlanes();
7006 if (r_timereport_active)
7007 R_TimeReport("watermodels");
7009 if (r_waterstate.numwaterplanes)
7011 R_Water_ProcessPlanes();
7012 if (r_timereport_active)
7013 R_TimeReport("waterscenes");
7017 extern void R_DrawLightningBeams (void);
7018 extern void VM_CL_AddPolygonsToMeshQueue (void);
7019 extern void R_DrawPortals (void);
7020 extern cvar_t cl_locs_show;
7021 static void R_DrawLocs(void);
7022 static void R_DrawEntityBBoxes(void);
7023 static void R_DrawModelDecals(void);
7024 extern void R_DrawModelShadows(void);
7025 extern void R_DrawModelShadowMaps(void);
7026 extern cvar_t cl_decals_newsystem;
7027 extern qboolean r_shadow_usingdeferredprepass;
7028 void R_RenderScene(void)
7030 qboolean shadowmapping = false;
7032 if (r_timereport_active)
7033 R_TimeReport("beginscene");
7035 r_refdef.stats.renders++;
7039 // don't let sound skip if going slow
7040 if (r_refdef.scene.extraupdate)
7043 R_MeshQueue_BeginScene();
7047 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);
7049 if (r_timereport_active)
7050 R_TimeReport("skystartframe");
7052 if (cl.csqc_vidvars.drawworld)
7054 // don't let sound skip if going slow
7055 if (r_refdef.scene.extraupdate)
7058 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7060 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7061 if (r_timereport_active)
7062 R_TimeReport("worldsky");
7065 if (R_DrawBrushModelsSky() && r_timereport_active)
7066 R_TimeReport("bmodelsky");
7068 if (skyrendermasked && skyrenderlater)
7070 // we have to force off the water clipping plane while rendering sky
7074 if (r_timereport_active)
7075 R_TimeReport("sky");
7079 R_Shadow_PrepareLights();
7080 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7081 R_Shadow_PrepareModelShadows();
7082 if (r_timereport_active)
7083 R_TimeReport("preparelights");
7085 if (R_Shadow_ShadowMappingEnabled())
7086 shadowmapping = true;
7088 if (r_shadow_usingdeferredprepass)
7089 R_Shadow_DrawPrepass();
7091 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7093 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7094 if (r_timereport_active)
7095 R_TimeReport("worlddepth");
7097 if (r_depthfirst.integer >= 2)
7099 R_DrawModelsDepth();
7100 if (r_timereport_active)
7101 R_TimeReport("modeldepth");
7104 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7106 R_DrawModelShadowMaps();
7107 R_ResetViewRendering3D();
7108 // don't let sound skip if going slow
7109 if (r_refdef.scene.extraupdate)
7113 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7115 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7116 if (r_timereport_active)
7117 R_TimeReport("world");
7120 // don't let sound skip if going slow
7121 if (r_refdef.scene.extraupdate)
7125 if (r_timereport_active)
7126 R_TimeReport("models");
7128 // don't let sound skip if going slow
7129 if (r_refdef.scene.extraupdate)
7132 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7134 R_DrawModelShadows();
7135 R_ResetViewRendering3D();
7136 // don't let sound skip if going slow
7137 if (r_refdef.scene.extraupdate)
7141 if (!r_shadow_usingdeferredprepass)
7143 R_Shadow_DrawLights();
7144 if (r_timereport_active)
7145 R_TimeReport("rtlights");
7148 // don't let sound skip if going slow
7149 if (r_refdef.scene.extraupdate)
7152 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7154 R_DrawModelShadows();
7155 R_ResetViewRendering3D();
7156 // don't let sound skip if going slow
7157 if (r_refdef.scene.extraupdate)
7161 if (cl.csqc_vidvars.drawworld)
7163 if (cl_decals_newsystem.integer)
7165 R_DrawModelDecals();
7166 if (r_timereport_active)
7167 R_TimeReport("modeldecals");
7172 if (r_timereport_active)
7173 R_TimeReport("decals");
7177 if (r_timereport_active)
7178 R_TimeReport("particles");
7181 if (r_timereport_active)
7182 R_TimeReport("explosions");
7184 R_DrawLightningBeams();
7185 if (r_timereport_active)
7186 R_TimeReport("lightning");
7189 VM_CL_AddPolygonsToMeshQueue();
7191 if (r_refdef.view.showdebug)
7193 if (cl_locs_show.integer)
7196 if (r_timereport_active)
7197 R_TimeReport("showlocs");
7200 if (r_drawportals.integer)
7203 if (r_timereport_active)
7204 R_TimeReport("portals");
7207 if (r_showbboxes.value > 0)
7209 R_DrawEntityBBoxes();
7210 if (r_timereport_active)
7211 R_TimeReport("bboxes");
7215 if (r_transparent.integer)
7217 R_MeshQueue_RenderTransparent();
7218 if (r_timereport_active)
7219 R_TimeReport("drawtrans");
7222 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))
7224 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7225 if (r_timereport_active)
7226 R_TimeReport("worlddebug");
7227 R_DrawModelsDebug();
7228 if (r_timereport_active)
7229 R_TimeReport("modeldebug");
7232 if (cl.csqc_vidvars.drawworld)
7234 R_Shadow_DrawCoronas();
7235 if (r_timereport_active)
7236 R_TimeReport("coronas");
7241 GL_DepthTest(false);
7242 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7243 GL_Color(1, 1, 1, 1);
7244 qglBegin(GL_POLYGON);
7245 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7246 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7247 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7248 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7250 qglBegin(GL_POLYGON);
7251 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]);
7252 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]);
7253 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]);
7254 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]);
7256 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7260 // don't let sound skip if going slow
7261 if (r_refdef.scene.extraupdate)
7264 R_ResetViewRendering2D();
7267 static const unsigned short bboxelements[36] =
7277 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7280 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7282 RSurf_ActiveWorldEntity();
7284 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7285 GL_DepthMask(false);
7286 GL_DepthRange(0, 1);
7287 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7288 // R_Mesh_ResetTextureState();
7290 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7291 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7292 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7293 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7294 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7295 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7296 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7297 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7298 R_FillColors(color4f, 8, cr, cg, cb, ca);
7299 if (r_refdef.fogenabled)
7301 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7303 f1 = RSurf_FogVertex(v);
7305 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7306 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7307 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7310 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7311 R_Mesh_ResetTextureState();
7312 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7313 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7316 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7320 prvm_edict_t *edict;
7321 prvm_prog_t *prog_save = prog;
7323 // this function draws bounding boxes of server entities
7327 GL_CullFace(GL_NONE);
7328 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7332 for (i = 0;i < numsurfaces;i++)
7334 edict = PRVM_EDICT_NUM(surfacelist[i]);
7335 switch ((int)PRVM_serveredictfloat(edict, solid))
7337 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7338 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7339 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7340 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7341 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7342 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7344 color[3] *= r_showbboxes.value;
7345 color[3] = bound(0, color[3], 1);
7346 GL_DepthTest(!r_showdisabledepthtest.integer);
7347 GL_CullFace(r_refdef.view.cullface_front);
7348 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7354 static void R_DrawEntityBBoxes(void)
7357 prvm_edict_t *edict;
7359 prvm_prog_t *prog_save = prog;
7361 // this function draws bounding boxes of server entities
7367 for (i = 0;i < prog->num_edicts;i++)
7369 edict = PRVM_EDICT_NUM(i);
7370 if (edict->priv.server->free)
7372 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7373 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7375 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7377 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7378 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7384 static const int nomodelelement3i[24] =
7396 static const unsigned short nomodelelement3s[24] =
7408 static const float nomodelvertex3f[6*3] =
7418 static const float nomodelcolor4f[6*4] =
7420 0.0f, 0.0f, 0.5f, 1.0f,
7421 0.0f, 0.0f, 0.5f, 1.0f,
7422 0.0f, 0.5f, 0.0f, 1.0f,
7423 0.0f, 0.5f, 0.0f, 1.0f,
7424 0.5f, 0.0f, 0.0f, 1.0f,
7425 0.5f, 0.0f, 0.0f, 1.0f
7428 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7434 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);
7436 // this is only called once per entity so numsurfaces is always 1, and
7437 // surfacelist is always {0}, so this code does not handle batches
7439 if (rsurface.ent_flags & RENDER_ADDITIVE)
7441 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7442 GL_DepthMask(false);
7444 else if (rsurface.colormod[3] < 1)
7446 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7447 GL_DepthMask(false);
7451 GL_BlendFunc(GL_ONE, GL_ZERO);
7454 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7455 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7456 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7457 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7458 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7459 for (i = 0, c = color4f;i < 6;i++, c += 4)
7461 c[0] *= rsurface.colormod[0];
7462 c[1] *= rsurface.colormod[1];
7463 c[2] *= rsurface.colormod[2];
7464 c[3] *= rsurface.colormod[3];
7466 if (r_refdef.fogenabled)
7468 for (i = 0, c = color4f;i < 6;i++, c += 4)
7470 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7472 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7473 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7474 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7477 // R_Mesh_ResetTextureState();
7478 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7479 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7480 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7483 void R_DrawNoModel(entity_render_t *ent)
7486 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7487 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7488 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7490 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7493 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7495 vec3_t right1, right2, diff, normal;
7497 VectorSubtract (org2, org1, normal);
7499 // calculate 'right' vector for start
7500 VectorSubtract (r_refdef.view.origin, org1, diff);
7501 CrossProduct (normal, diff, right1);
7502 VectorNormalize (right1);
7504 // calculate 'right' vector for end
7505 VectorSubtract (r_refdef.view.origin, org2, diff);
7506 CrossProduct (normal, diff, right2);
7507 VectorNormalize (right2);
7509 vert[ 0] = org1[0] + width * right1[0];
7510 vert[ 1] = org1[1] + width * right1[1];
7511 vert[ 2] = org1[2] + width * right1[2];
7512 vert[ 3] = org1[0] - width * right1[0];
7513 vert[ 4] = org1[1] - width * right1[1];
7514 vert[ 5] = org1[2] - width * right1[2];
7515 vert[ 6] = org2[0] - width * right2[0];
7516 vert[ 7] = org2[1] - width * right2[1];
7517 vert[ 8] = org2[2] - width * right2[2];
7518 vert[ 9] = org2[0] + width * right2[0];
7519 vert[10] = org2[1] + width * right2[1];
7520 vert[11] = org2[2] + width * right2[2];
7523 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)
7525 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7526 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7527 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7528 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7529 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7530 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7531 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7532 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7533 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7534 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7535 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7536 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7539 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7544 VectorSet(v, x, y, z);
7545 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7546 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7548 if (i == mesh->numvertices)
7550 if (mesh->numvertices < mesh->maxvertices)
7552 VectorCopy(v, vertex3f);
7553 mesh->numvertices++;
7555 return mesh->numvertices;
7561 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7565 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7566 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7567 e = mesh->element3i + mesh->numtriangles * 3;
7568 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7570 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7571 if (mesh->numtriangles < mesh->maxtriangles)
7576 mesh->numtriangles++;
7578 element[1] = element[2];
7582 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7586 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7587 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7588 e = mesh->element3i + mesh->numtriangles * 3;
7589 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7591 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7592 if (mesh->numtriangles < mesh->maxtriangles)
7597 mesh->numtriangles++;
7599 element[1] = element[2];
7603 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7604 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7606 int planenum, planenum2;
7609 mplane_t *plane, *plane2;
7611 double temppoints[2][256*3];
7612 // figure out how large a bounding box we need to properly compute this brush
7614 for (w = 0;w < numplanes;w++)
7615 maxdist = max(maxdist, fabs(planes[w].dist));
7616 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7617 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7618 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7622 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7623 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7625 if (planenum2 == planenum)
7627 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);
7630 if (tempnumpoints < 3)
7632 // generate elements forming a triangle fan for this polygon
7633 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7637 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)
7639 texturelayer_t *layer;
7640 layer = t->currentlayers + t->currentnumlayers++;
7642 layer->depthmask = depthmask;
7643 layer->blendfunc1 = blendfunc1;
7644 layer->blendfunc2 = blendfunc2;
7645 layer->texture = texture;
7646 layer->texmatrix = *matrix;
7647 layer->color[0] = r;
7648 layer->color[1] = g;
7649 layer->color[2] = b;
7650 layer->color[3] = a;
7653 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7655 if(parms[0] == 0 && parms[1] == 0)
7657 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7658 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7663 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7666 index = parms[2] + rsurface.shadertime * parms[3];
7667 index -= floor(index);
7668 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7671 case Q3WAVEFUNC_NONE:
7672 case Q3WAVEFUNC_NOISE:
7673 case Q3WAVEFUNC_COUNT:
7676 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7677 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7678 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7679 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7680 case Q3WAVEFUNC_TRIANGLE:
7682 f = index - floor(index);
7695 f = parms[0] + parms[1] * f;
7696 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7697 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7701 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7707 matrix4x4_t matrix, temp;
7708 switch(tcmod->tcmod)
7712 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7713 matrix = r_waterscrollmatrix;
7715 matrix = identitymatrix;
7717 case Q3TCMOD_ENTITYTRANSLATE:
7718 // this is used in Q3 to allow the gamecode to control texcoord
7719 // scrolling on the entity, which is not supported in darkplaces yet.
7720 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7722 case Q3TCMOD_ROTATE:
7723 f = tcmod->parms[0] * rsurface.shadertime;
7724 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7725 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7726 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7729 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7731 case Q3TCMOD_SCROLL:
7732 // extra care is needed because of precision breakdown with large values of time
7733 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7734 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7735 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7737 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7738 w = (int) tcmod->parms[0];
7739 h = (int) tcmod->parms[1];
7740 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7742 idx = (int) floor(f * w * h);
7743 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7745 case Q3TCMOD_STRETCH:
7746 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7747 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7749 case Q3TCMOD_TRANSFORM:
7750 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7751 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7752 VectorSet(tcmat + 6, 0 , 0 , 1);
7753 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7754 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7756 case Q3TCMOD_TURBULENT:
7757 // this is handled in the RSurf_PrepareVertices function
7758 matrix = identitymatrix;
7762 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7765 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7767 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7768 char name[MAX_QPATH];
7769 skinframe_t *skinframe;
7770 unsigned char pixels[296*194];
7771 strlcpy(cache->name, skinname, sizeof(cache->name));
7772 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7773 if (developer_loading.integer)
7774 Con_Printf("loading %s\n", name);
7775 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7776 if (!skinframe || !skinframe->base)
7779 fs_offset_t filesize;
7781 f = FS_LoadFile(name, tempmempool, true, &filesize);
7784 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7785 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7789 cache->skinframe = skinframe;
7792 texture_t *R_GetCurrentTexture(texture_t *t)
7795 const entity_render_t *ent = rsurface.entity;
7796 dp_model_t *model = ent->model;
7797 q3shaderinfo_layer_tcmod_t *tcmod;
7799 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7800 return t->currentframe;
7801 t->update_lastrenderframe = r_textureframe;
7802 t->update_lastrenderentity = (void *)ent;
7804 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7805 t->camera_entity = ent->entitynumber;
7807 t->camera_entity = 0;
7809 // switch to an alternate material if this is a q1bsp animated material
7811 texture_t *texture = t;
7812 int s = rsurface.ent_skinnum;
7813 if ((unsigned int)s >= (unsigned int)model->numskins)
7815 if (model->skinscenes)
7817 if (model->skinscenes[s].framecount > 1)
7818 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7820 s = model->skinscenes[s].firstframe;
7823 t = t + s * model->num_surfaces;
7826 // use an alternate animation if the entity's frame is not 0,
7827 // and only if the texture has an alternate animation
7828 if (rsurface.ent_alttextures && t->anim_total[1])
7829 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7831 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7833 texture->currentframe = t;
7836 // update currentskinframe to be a qw skin or animation frame
7837 if (rsurface.ent_qwskin >= 0)
7839 i = rsurface.ent_qwskin;
7840 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7842 r_qwskincache_size = cl.maxclients;
7844 Mem_Free(r_qwskincache);
7845 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7847 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7848 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7849 t->currentskinframe = r_qwskincache[i].skinframe;
7850 if (t->currentskinframe == NULL)
7851 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7853 else if (t->numskinframes >= 2)
7854 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7855 if (t->backgroundnumskinframes >= 2)
7856 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7858 t->currentmaterialflags = t->basematerialflags;
7859 t->currentalpha = rsurface.colormod[3];
7860 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7861 t->currentalpha *= r_wateralpha.value;
7862 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7863 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7864 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7865 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7866 if (!(rsurface.ent_flags & RENDER_LIGHT))
7867 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7868 else if (FAKELIGHT_ENABLED)
7870 // no modellight if using fakelight for the map
7872 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7874 // pick a model lighting mode
7875 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7876 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7878 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7880 if (rsurface.ent_flags & RENDER_ADDITIVE)
7881 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7882 else if (t->currentalpha < 1)
7883 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7884 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7885 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7886 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7887 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7888 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7889 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7890 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7891 if (t->backgroundnumskinframes)
7892 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7893 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7895 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7896 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7899 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7900 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7902 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7903 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7905 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7906 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7908 // there is no tcmod
7909 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7911 t->currenttexmatrix = r_waterscrollmatrix;
7912 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7914 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7916 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7917 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7920 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7921 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7922 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7923 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7925 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7926 if (t->currentskinframe->qpixels)
7927 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7928 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7929 if (!t->basetexture)
7930 t->basetexture = r_texture_notexture;
7931 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7932 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7933 t->nmaptexture = t->currentskinframe->nmap;
7934 if (!t->nmaptexture)
7935 t->nmaptexture = r_texture_blanknormalmap;
7936 t->glosstexture = r_texture_black;
7937 t->glowtexture = t->currentskinframe->glow;
7938 t->fogtexture = t->currentskinframe->fog;
7939 t->reflectmasktexture = t->currentskinframe->reflect;
7940 if (t->backgroundnumskinframes)
7942 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7943 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7944 t->backgroundglosstexture = r_texture_black;
7945 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7946 if (!t->backgroundnmaptexture)
7947 t->backgroundnmaptexture = r_texture_blanknormalmap;
7951 t->backgroundbasetexture = r_texture_white;
7952 t->backgroundnmaptexture = r_texture_blanknormalmap;
7953 t->backgroundglosstexture = r_texture_black;
7954 t->backgroundglowtexture = NULL;
7956 t->specularpower = r_shadow_glossexponent.value;
7957 // TODO: store reference values for these in the texture?
7958 t->specularscale = 0;
7959 if (r_shadow_gloss.integer > 0)
7961 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7963 if (r_shadow_glossintensity.value > 0)
7965 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7966 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7967 t->specularscale = r_shadow_glossintensity.value;
7970 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7972 t->glosstexture = r_texture_white;
7973 t->backgroundglosstexture = r_texture_white;
7974 t->specularscale = r_shadow_gloss2intensity.value;
7975 t->specularpower = r_shadow_gloss2exponent.value;
7978 t->specularscale *= t->specularscalemod;
7979 t->specularpower *= t->specularpowermod;
7980 t->rtlightambient = 0;
7982 // lightmaps mode looks bad with dlights using actual texturing, so turn
7983 // off the colormap and glossmap, but leave the normalmap on as it still
7984 // accurately represents the shading involved
7985 if (gl_lightmaps.integer)
7987 t->basetexture = r_texture_grey128;
7988 t->pantstexture = r_texture_black;
7989 t->shirttexture = r_texture_black;
7990 t->nmaptexture = r_texture_blanknormalmap;
7991 t->glosstexture = r_texture_black;
7992 t->glowtexture = NULL;
7993 t->fogtexture = NULL;
7994 t->reflectmasktexture = NULL;
7995 t->backgroundbasetexture = NULL;
7996 t->backgroundnmaptexture = r_texture_blanknormalmap;
7997 t->backgroundglosstexture = r_texture_black;
7998 t->backgroundglowtexture = NULL;
7999 t->specularscale = 0;
8000 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8003 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8004 VectorClear(t->dlightcolor);
8005 t->currentnumlayers = 0;
8006 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8008 int blendfunc1, blendfunc2;
8010 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8012 blendfunc1 = GL_SRC_ALPHA;
8013 blendfunc2 = GL_ONE;
8015 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8017 blendfunc1 = GL_SRC_ALPHA;
8018 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8020 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8022 blendfunc1 = t->customblendfunc[0];
8023 blendfunc2 = t->customblendfunc[1];
8027 blendfunc1 = GL_ONE;
8028 blendfunc2 = GL_ZERO;
8030 // don't colormod evilblend textures
8031 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8032 VectorSet(t->lightmapcolor, 1, 1, 1);
8033 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8034 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8036 // fullbright is not affected by r_refdef.lightmapintensity
8037 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]);
8038 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8039 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]);
8040 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8041 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]);
8045 vec3_t ambientcolor;
8047 // set the color tint used for lights affecting this surface
8048 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8050 // q3bsp has no lightmap updates, so the lightstylevalue that
8051 // would normally be baked into the lightmap must be
8052 // applied to the color
8053 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8054 if (model->type == mod_brushq3)
8055 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8056 colorscale *= r_refdef.lightmapintensity;
8057 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8058 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8059 // basic lit geometry
8060 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]);
8061 // add pants/shirt if needed
8062 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8063 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]);
8064 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8065 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]);
8066 // now add ambient passes if needed
8067 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8069 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]);
8070 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8071 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]);
8072 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8073 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]);
8076 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8077 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]);
8078 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8080 // if this is opaque use alpha blend which will darken the earlier
8083 // if this is an alpha blended material, all the earlier passes
8084 // were darkened by fog already, so we only need to add the fog
8085 // color ontop through the fog mask texture
8087 // if this is an additive blended material, all the earlier passes
8088 // were darkened by fog already, and we should not add fog color
8089 // (because the background was not darkened, there is no fog color
8090 // that was lost behind it).
8091 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]);
8095 return t->currentframe;
8098 rsurfacestate_t rsurface;
8100 void RSurf_ActiveWorldEntity(void)
8102 dp_model_t *model = r_refdef.scene.worldmodel;
8103 //if (rsurface.entity == r_refdef.scene.worldentity)
8105 rsurface.entity = r_refdef.scene.worldentity;
8106 rsurface.skeleton = NULL;
8107 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8108 rsurface.ent_skinnum = 0;
8109 rsurface.ent_qwskin = -1;
8110 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8111 rsurface.shadertime = r_refdef.scene.time;
8112 rsurface.matrix = identitymatrix;
8113 rsurface.inversematrix = identitymatrix;
8114 rsurface.matrixscale = 1;
8115 rsurface.inversematrixscale = 1;
8116 R_EntityMatrix(&identitymatrix);
8117 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8118 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8119 rsurface.fograngerecip = r_refdef.fograngerecip;
8120 rsurface.fogheightfade = r_refdef.fogheightfade;
8121 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8122 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8123 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8124 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8125 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8126 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8127 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8128 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8129 rsurface.colormod[3] = 1;
8130 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);
8131 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8132 rsurface.frameblend[0].lerp = 1;
8133 rsurface.ent_alttextures = false;
8134 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8135 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8136 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8137 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8138 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8139 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8140 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8141 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8142 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8143 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8144 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8145 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8146 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8147 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8148 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8149 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8150 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8151 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8152 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8153 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8154 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8155 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8156 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8157 rsurface.modelelement3i = model->surfmesh.data_element3i;
8158 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8159 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8160 rsurface.modelelement3s = model->surfmesh.data_element3s;
8161 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8162 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8163 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8164 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8165 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8166 rsurface.modelsurfaces = model->data_surfaces;
8167 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8168 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8169 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8170 rsurface.modelgeneratedvertex = false;
8171 rsurface.batchgeneratedvertex = false;
8172 rsurface.batchfirstvertex = 0;
8173 rsurface.batchnumvertices = 0;
8174 rsurface.batchfirsttriangle = 0;
8175 rsurface.batchnumtriangles = 0;
8176 rsurface.batchvertex3f = NULL;
8177 rsurface.batchvertex3f_vertexbuffer = NULL;
8178 rsurface.batchvertex3f_bufferoffset = 0;
8179 rsurface.batchsvector3f = NULL;
8180 rsurface.batchsvector3f_vertexbuffer = NULL;
8181 rsurface.batchsvector3f_bufferoffset = 0;
8182 rsurface.batchtvector3f = NULL;
8183 rsurface.batchtvector3f_vertexbuffer = NULL;
8184 rsurface.batchtvector3f_bufferoffset = 0;
8185 rsurface.batchnormal3f = NULL;
8186 rsurface.batchnormal3f_vertexbuffer = NULL;
8187 rsurface.batchnormal3f_bufferoffset = 0;
8188 rsurface.batchlightmapcolor4f = NULL;
8189 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8190 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8191 rsurface.batchtexcoordtexture2f = NULL;
8192 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8193 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8194 rsurface.batchtexcoordlightmap2f = NULL;
8195 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8196 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8197 rsurface.batchvertexmesh = NULL;
8198 rsurface.batchvertexmeshbuffer = NULL;
8199 rsurface.batchvertex3fbuffer = NULL;
8200 rsurface.batchelement3i = NULL;
8201 rsurface.batchelement3i_indexbuffer = NULL;
8202 rsurface.batchelement3i_bufferoffset = 0;
8203 rsurface.batchelement3s = NULL;
8204 rsurface.batchelement3s_indexbuffer = NULL;
8205 rsurface.batchelement3s_bufferoffset = 0;
8206 rsurface.passcolor4f = NULL;
8207 rsurface.passcolor4f_vertexbuffer = NULL;
8208 rsurface.passcolor4f_bufferoffset = 0;
8211 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8213 dp_model_t *model = ent->model;
8214 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8216 rsurface.entity = (entity_render_t *)ent;
8217 rsurface.skeleton = ent->skeleton;
8218 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8219 rsurface.ent_skinnum = ent->skinnum;
8220 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;
8221 rsurface.ent_flags = ent->flags;
8222 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8223 rsurface.matrix = ent->matrix;
8224 rsurface.inversematrix = ent->inversematrix;
8225 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8226 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8227 R_EntityMatrix(&rsurface.matrix);
8228 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8229 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8230 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8231 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8232 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8233 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8234 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8235 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8236 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8237 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8238 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8239 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8240 rsurface.colormod[3] = ent->alpha;
8241 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8242 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8243 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8244 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8245 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8246 if (ent->model->brush.submodel && !prepass)
8248 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8249 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8251 if (model->surfmesh.isanimated && model->AnimateVertices)
8253 if (ent->animcache_vertex3f)
8255 rsurface.modelvertex3f = ent->animcache_vertex3f;
8256 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8257 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8258 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8259 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8260 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8261 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8263 else if (wanttangents)
8265 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8266 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8267 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8268 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8269 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8270 rsurface.modelvertexmesh = NULL;
8271 rsurface.modelvertexmeshbuffer = NULL;
8272 rsurface.modelvertex3fbuffer = NULL;
8274 else if (wantnormals)
8276 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8277 rsurface.modelsvector3f = NULL;
8278 rsurface.modeltvector3f = NULL;
8279 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8280 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8281 rsurface.modelvertexmesh = NULL;
8282 rsurface.modelvertexmeshbuffer = NULL;
8283 rsurface.modelvertex3fbuffer = NULL;
8287 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8288 rsurface.modelsvector3f = NULL;
8289 rsurface.modeltvector3f = NULL;
8290 rsurface.modelnormal3f = NULL;
8291 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8292 rsurface.modelvertexmesh = NULL;
8293 rsurface.modelvertexmeshbuffer = NULL;
8294 rsurface.modelvertex3fbuffer = NULL;
8296 rsurface.modelvertex3f_vertexbuffer = 0;
8297 rsurface.modelvertex3f_bufferoffset = 0;
8298 rsurface.modelsvector3f_vertexbuffer = 0;
8299 rsurface.modelsvector3f_bufferoffset = 0;
8300 rsurface.modeltvector3f_vertexbuffer = 0;
8301 rsurface.modeltvector3f_bufferoffset = 0;
8302 rsurface.modelnormal3f_vertexbuffer = 0;
8303 rsurface.modelnormal3f_bufferoffset = 0;
8304 rsurface.modelgeneratedvertex = true;
8308 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8309 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8310 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8311 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8312 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8313 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8314 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8315 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8316 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8317 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8318 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8319 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8320 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8321 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8322 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8323 rsurface.modelgeneratedvertex = false;
8325 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8326 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8327 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8328 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8329 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8330 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8331 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8332 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8333 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8334 rsurface.modelelement3i = model->surfmesh.data_element3i;
8335 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8336 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8337 rsurface.modelelement3s = model->surfmesh.data_element3s;
8338 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8339 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8340 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8341 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8342 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8343 rsurface.modelsurfaces = model->data_surfaces;
8344 rsurface.batchgeneratedvertex = false;
8345 rsurface.batchfirstvertex = 0;
8346 rsurface.batchnumvertices = 0;
8347 rsurface.batchfirsttriangle = 0;
8348 rsurface.batchnumtriangles = 0;
8349 rsurface.batchvertex3f = NULL;
8350 rsurface.batchvertex3f_vertexbuffer = NULL;
8351 rsurface.batchvertex3f_bufferoffset = 0;
8352 rsurface.batchsvector3f = NULL;
8353 rsurface.batchsvector3f_vertexbuffer = NULL;
8354 rsurface.batchsvector3f_bufferoffset = 0;
8355 rsurface.batchtvector3f = NULL;
8356 rsurface.batchtvector3f_vertexbuffer = NULL;
8357 rsurface.batchtvector3f_bufferoffset = 0;
8358 rsurface.batchnormal3f = NULL;
8359 rsurface.batchnormal3f_vertexbuffer = NULL;
8360 rsurface.batchnormal3f_bufferoffset = 0;
8361 rsurface.batchlightmapcolor4f = NULL;
8362 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8363 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8364 rsurface.batchtexcoordtexture2f = NULL;
8365 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8366 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8367 rsurface.batchtexcoordlightmap2f = NULL;
8368 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8369 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8370 rsurface.batchvertexmesh = NULL;
8371 rsurface.batchvertexmeshbuffer = NULL;
8372 rsurface.batchvertex3fbuffer = NULL;
8373 rsurface.batchelement3i = NULL;
8374 rsurface.batchelement3i_indexbuffer = NULL;
8375 rsurface.batchelement3i_bufferoffset = 0;
8376 rsurface.batchelement3s = NULL;
8377 rsurface.batchelement3s_indexbuffer = NULL;
8378 rsurface.batchelement3s_bufferoffset = 0;
8379 rsurface.passcolor4f = NULL;
8380 rsurface.passcolor4f_vertexbuffer = NULL;
8381 rsurface.passcolor4f_bufferoffset = 0;
8384 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)
8386 rsurface.entity = r_refdef.scene.worldentity;
8387 rsurface.skeleton = NULL;
8388 rsurface.ent_skinnum = 0;
8389 rsurface.ent_qwskin = -1;
8390 rsurface.ent_flags = entflags;
8391 rsurface.shadertime = r_refdef.scene.time - shadertime;
8392 rsurface.modelnumvertices = numvertices;
8393 rsurface.modelnumtriangles = numtriangles;
8394 rsurface.matrix = *matrix;
8395 rsurface.inversematrix = *inversematrix;
8396 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8397 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8398 R_EntityMatrix(&rsurface.matrix);
8399 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8400 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8401 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8402 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8403 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8404 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8405 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8406 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8407 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8408 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8409 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8410 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8411 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);
8412 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8413 rsurface.frameblend[0].lerp = 1;
8414 rsurface.ent_alttextures = false;
8415 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8416 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8419 rsurface.modelvertex3f = (float *)vertex3f;
8420 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8421 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8422 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8424 else if (wantnormals)
8426 rsurface.modelvertex3f = (float *)vertex3f;
8427 rsurface.modelsvector3f = NULL;
8428 rsurface.modeltvector3f = NULL;
8429 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8433 rsurface.modelvertex3f = (float *)vertex3f;
8434 rsurface.modelsvector3f = NULL;
8435 rsurface.modeltvector3f = NULL;
8436 rsurface.modelnormal3f = NULL;
8438 rsurface.modelvertexmesh = NULL;
8439 rsurface.modelvertexmeshbuffer = NULL;
8440 rsurface.modelvertex3fbuffer = NULL;
8441 rsurface.modelvertex3f_vertexbuffer = 0;
8442 rsurface.modelvertex3f_bufferoffset = 0;
8443 rsurface.modelsvector3f_vertexbuffer = 0;
8444 rsurface.modelsvector3f_bufferoffset = 0;
8445 rsurface.modeltvector3f_vertexbuffer = 0;
8446 rsurface.modeltvector3f_bufferoffset = 0;
8447 rsurface.modelnormal3f_vertexbuffer = 0;
8448 rsurface.modelnormal3f_bufferoffset = 0;
8449 rsurface.modelgeneratedvertex = true;
8450 rsurface.modellightmapcolor4f = (float *)color4f;
8451 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8452 rsurface.modellightmapcolor4f_bufferoffset = 0;
8453 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8454 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8455 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8456 rsurface.modeltexcoordlightmap2f = NULL;
8457 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8458 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8459 rsurface.modelelement3i = (int *)element3i;
8460 rsurface.modelelement3i_indexbuffer = NULL;
8461 rsurface.modelelement3i_bufferoffset = 0;
8462 rsurface.modelelement3s = (unsigned short *)element3s;
8463 rsurface.modelelement3s_indexbuffer = NULL;
8464 rsurface.modelelement3s_bufferoffset = 0;
8465 rsurface.modellightmapoffsets = NULL;
8466 rsurface.modelsurfaces = NULL;
8467 rsurface.batchgeneratedvertex = false;
8468 rsurface.batchfirstvertex = 0;
8469 rsurface.batchnumvertices = 0;
8470 rsurface.batchfirsttriangle = 0;
8471 rsurface.batchnumtriangles = 0;
8472 rsurface.batchvertex3f = NULL;
8473 rsurface.batchvertex3f_vertexbuffer = NULL;
8474 rsurface.batchvertex3f_bufferoffset = 0;
8475 rsurface.batchsvector3f = NULL;
8476 rsurface.batchsvector3f_vertexbuffer = NULL;
8477 rsurface.batchsvector3f_bufferoffset = 0;
8478 rsurface.batchtvector3f = NULL;
8479 rsurface.batchtvector3f_vertexbuffer = NULL;
8480 rsurface.batchtvector3f_bufferoffset = 0;
8481 rsurface.batchnormal3f = NULL;
8482 rsurface.batchnormal3f_vertexbuffer = NULL;
8483 rsurface.batchnormal3f_bufferoffset = 0;
8484 rsurface.batchlightmapcolor4f = NULL;
8485 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8486 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8487 rsurface.batchtexcoordtexture2f = NULL;
8488 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8489 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8490 rsurface.batchtexcoordlightmap2f = NULL;
8491 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8492 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8493 rsurface.batchvertexmesh = NULL;
8494 rsurface.batchvertexmeshbuffer = NULL;
8495 rsurface.batchvertex3fbuffer = NULL;
8496 rsurface.batchelement3i = NULL;
8497 rsurface.batchelement3i_indexbuffer = NULL;
8498 rsurface.batchelement3i_bufferoffset = 0;
8499 rsurface.batchelement3s = NULL;
8500 rsurface.batchelement3s_indexbuffer = NULL;
8501 rsurface.batchelement3s_bufferoffset = 0;
8502 rsurface.passcolor4f = NULL;
8503 rsurface.passcolor4f_vertexbuffer = NULL;
8504 rsurface.passcolor4f_bufferoffset = 0;
8506 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8508 if ((wantnormals || wanttangents) && !normal3f)
8510 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8511 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8513 if (wanttangents && !svector3f)
8515 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8516 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8517 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8522 float RSurf_FogPoint(const float *v)
8524 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8525 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8526 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8527 float FogHeightFade = r_refdef.fogheightfade;
8529 unsigned int fogmasktableindex;
8530 if (r_refdef.fogplaneviewabove)
8531 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8533 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8534 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8535 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8538 float RSurf_FogVertex(const float *v)
8540 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8541 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8542 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8543 float FogHeightFade = rsurface.fogheightfade;
8545 unsigned int fogmasktableindex;
8546 if (r_refdef.fogplaneviewabove)
8547 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8549 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8550 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8551 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8554 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8557 for (i = 0;i < numelements;i++)
8558 outelement3i[i] = inelement3i[i] + adjust;
8561 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8562 extern cvar_t gl_vbo;
8563 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8571 int surfacefirsttriangle;
8572 int surfacenumtriangles;
8573 int surfacefirstvertex;
8574 int surfaceendvertex;
8575 int surfacenumvertices;
8576 int batchnumvertices;
8577 int batchnumtriangles;
8581 qboolean dynamicvertex;
8585 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8587 q3shaderinfo_deform_t *deform;
8588 const msurface_t *surface, *firstsurface;
8589 r_vertexmesh_t *vertexmesh;
8590 if (!texturenumsurfaces)
8592 // find vertex range of this surface batch
8594 firstsurface = texturesurfacelist[0];
8595 firsttriangle = firstsurface->num_firsttriangle;
8596 batchnumvertices = 0;
8597 batchnumtriangles = 0;
8598 firstvertex = endvertex = firstsurface->num_firstvertex;
8599 for (i = 0;i < texturenumsurfaces;i++)
8601 surface = texturesurfacelist[i];
8602 if (surface != firstsurface + i)
8604 surfacefirstvertex = surface->num_firstvertex;
8605 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8606 surfacenumvertices = surface->num_vertices;
8607 surfacenumtriangles = surface->num_triangles;
8608 if (firstvertex > surfacefirstvertex)
8609 firstvertex = surfacefirstvertex;
8610 if (endvertex < surfaceendvertex)
8611 endvertex = surfaceendvertex;
8612 batchnumvertices += surfacenumvertices;
8613 batchnumtriangles += surfacenumtriangles;
8616 // we now know the vertex range used, and if there are any gaps in it
8617 rsurface.batchfirstvertex = firstvertex;
8618 rsurface.batchnumvertices = endvertex - firstvertex;
8619 rsurface.batchfirsttriangle = firsttriangle;
8620 rsurface.batchnumtriangles = batchnumtriangles;
8622 // this variable holds flags for which properties have been updated that
8623 // may require regenerating vertexmesh array...
8626 // check if any dynamic vertex processing must occur
8627 dynamicvertex = false;
8629 // if there is a chance of animated vertex colors, it's a dynamic batch
8630 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8632 dynamicvertex = true;
8633 batchneed |= BATCHNEED_NOGAPS;
8634 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8637 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8639 switch (deform->deform)
8642 case Q3DEFORM_PROJECTIONSHADOW:
8643 case Q3DEFORM_TEXT0:
8644 case Q3DEFORM_TEXT1:
8645 case Q3DEFORM_TEXT2:
8646 case Q3DEFORM_TEXT3:
8647 case Q3DEFORM_TEXT4:
8648 case Q3DEFORM_TEXT5:
8649 case Q3DEFORM_TEXT6:
8650 case Q3DEFORM_TEXT7:
8653 case Q3DEFORM_AUTOSPRITE:
8654 dynamicvertex = true;
8655 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8658 case Q3DEFORM_AUTOSPRITE2:
8659 dynamicvertex = true;
8660 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8661 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8663 case Q3DEFORM_NORMAL:
8664 dynamicvertex = true;
8665 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8666 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8669 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8670 break; // if wavefunc is a nop, ignore this transform
8671 dynamicvertex = true;
8672 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8673 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8675 case Q3DEFORM_BULGE:
8676 dynamicvertex = true;
8677 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8678 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8681 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8682 break; // if wavefunc is a nop, ignore this transform
8683 dynamicvertex = true;
8684 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8685 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8689 switch(rsurface.texture->tcgen.tcgen)
8692 case Q3TCGEN_TEXTURE:
8694 case Q3TCGEN_LIGHTMAP:
8695 dynamicvertex = true;
8696 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8697 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8699 case Q3TCGEN_VECTOR:
8700 dynamicvertex = true;
8701 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8702 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8704 case Q3TCGEN_ENVIRONMENT:
8705 dynamicvertex = true;
8706 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8707 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8710 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8712 dynamicvertex = true;
8713 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8714 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8717 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8719 dynamicvertex = true;
8720 batchneed |= BATCHNEED_NOGAPS;
8721 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8724 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8726 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8727 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8728 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8729 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8730 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8731 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8732 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8735 // when the model data has no vertex buffer (dynamic mesh), we need to
8737 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8738 batchneed |= BATCHNEED_NOGAPS;
8740 // if needsupdate, we have to do a dynamic vertex batch for sure
8741 if (needsupdate & batchneed)
8742 dynamicvertex = true;
8744 // see if we need to build vertexmesh from arrays
8745 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8746 dynamicvertex = true;
8748 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8749 // also some drivers strongly dislike firstvertex
8750 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8751 dynamicvertex = true;
8753 rsurface.batchvertex3f = rsurface.modelvertex3f;
8754 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8755 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8756 rsurface.batchsvector3f = rsurface.modelsvector3f;
8757 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8758 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8759 rsurface.batchtvector3f = rsurface.modeltvector3f;
8760 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8761 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8762 rsurface.batchnormal3f = rsurface.modelnormal3f;
8763 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8764 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8765 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8766 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8767 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8768 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8769 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8770 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8771 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8772 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8773 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8774 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8775 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8776 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8777 rsurface.batchelement3i = rsurface.modelelement3i;
8778 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8779 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8780 rsurface.batchelement3s = rsurface.modelelement3s;
8781 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8782 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8784 // if any dynamic vertex processing has to occur in software, we copy the
8785 // entire surface list together before processing to rebase the vertices
8786 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8788 // if any gaps exist and we do not have a static vertex buffer, we have to
8789 // copy the surface list together to avoid wasting upload bandwidth on the
8790 // vertices in the gaps.
8792 // if gaps exist and we have a static vertex buffer, we still have to
8793 // combine the index buffer ranges into one dynamic index buffer.
8795 // in all cases we end up with data that can be drawn in one call.
8799 // static vertex data, just set pointers...
8800 rsurface.batchgeneratedvertex = false;
8801 // if there are gaps, we want to build a combined index buffer,
8802 // otherwise use the original static buffer with an appropriate offset
8805 // build a new triangle elements array for this batch
8806 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8807 rsurface.batchfirsttriangle = 0;
8809 for (i = 0;i < texturenumsurfaces;i++)
8811 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8812 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8813 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8814 numtriangles += surfacenumtriangles;
8816 rsurface.batchelement3i_indexbuffer = NULL;
8817 rsurface.batchelement3i_bufferoffset = 0;
8818 rsurface.batchelement3s = NULL;
8819 rsurface.batchelement3s_indexbuffer = NULL;
8820 rsurface.batchelement3s_bufferoffset = 0;
8821 if (endvertex <= 65536)
8823 // make a 16bit (unsigned short) index array if possible
8824 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8825 for (i = 0;i < numtriangles*3;i++)
8826 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8832 // something needs software processing, do it for real...
8833 // we only directly handle separate array data in this case and then
8834 // generate interleaved data if needed...
8835 rsurface.batchgeneratedvertex = true;
8837 // now copy the vertex data into a combined array and make an index array
8838 // (this is what Quake3 does all the time)
8839 //if (gaps || rsurface.batchfirstvertex)
8841 rsurface.batchvertex3fbuffer = NULL;
8842 rsurface.batchvertexmesh = NULL;
8843 rsurface.batchvertexmeshbuffer = NULL;
8844 rsurface.batchvertex3f = NULL;
8845 rsurface.batchvertex3f_vertexbuffer = NULL;
8846 rsurface.batchvertex3f_bufferoffset = 0;
8847 rsurface.batchsvector3f = NULL;
8848 rsurface.batchsvector3f_vertexbuffer = NULL;
8849 rsurface.batchsvector3f_bufferoffset = 0;
8850 rsurface.batchtvector3f = NULL;
8851 rsurface.batchtvector3f_vertexbuffer = NULL;
8852 rsurface.batchtvector3f_bufferoffset = 0;
8853 rsurface.batchnormal3f = NULL;
8854 rsurface.batchnormal3f_vertexbuffer = NULL;
8855 rsurface.batchnormal3f_bufferoffset = 0;
8856 rsurface.batchlightmapcolor4f = NULL;
8857 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8858 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8859 rsurface.batchtexcoordtexture2f = NULL;
8860 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8861 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8862 rsurface.batchtexcoordlightmap2f = NULL;
8863 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8864 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8865 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8866 rsurface.batchelement3i_indexbuffer = NULL;
8867 rsurface.batchelement3i_bufferoffset = 0;
8868 rsurface.batchelement3s = NULL;
8869 rsurface.batchelement3s_indexbuffer = NULL;
8870 rsurface.batchelement3s_bufferoffset = 0;
8871 // we'll only be setting up certain arrays as needed
8872 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8873 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8874 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8875 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8876 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8877 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8878 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8880 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8881 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8883 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8884 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8885 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8886 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8887 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8888 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8891 for (i = 0;i < texturenumsurfaces;i++)
8893 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8894 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8895 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8896 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8897 // copy only the data requested
8898 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8899 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8900 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8902 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8904 if (rsurface.batchvertex3f)
8905 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8907 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8909 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8911 if (rsurface.modelnormal3f)
8912 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8914 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8916 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8918 if (rsurface.modelsvector3f)
8920 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8921 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8925 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8926 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8929 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8931 if (rsurface.modellightmapcolor4f)
8932 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8934 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8936 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8938 if (rsurface.modeltexcoordtexture2f)
8939 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8941 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8943 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8945 if (rsurface.modeltexcoordlightmap2f)
8946 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8948 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8951 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8952 numvertices += surfacenumvertices;
8953 numtriangles += surfacenumtriangles;
8956 // generate a 16bit index array as well if possible
8957 // (in general, dynamic batches fit)
8958 if (numvertices <= 65536)
8960 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8961 for (i = 0;i < numtriangles*3;i++)
8962 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8965 // since we've copied everything, the batch now starts at 0
8966 rsurface.batchfirstvertex = 0;
8967 rsurface.batchnumvertices = batchnumvertices;
8968 rsurface.batchfirsttriangle = 0;
8969 rsurface.batchnumtriangles = batchnumtriangles;
8972 // q1bsp surfaces rendered in vertex color mode have to have colors
8973 // calculated based on lightstyles
8974 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8976 // generate color arrays for the surfaces in this list
8981 const unsigned char *lm;
8982 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8983 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8984 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8986 for (i = 0;i < texturenumsurfaces;i++)
8988 surface = texturesurfacelist[i];
8989 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8990 surfacenumvertices = surface->num_vertices;
8991 if (surface->lightmapinfo->samples)
8993 for (j = 0;j < surfacenumvertices;j++)
8995 lm = surface->lightmapinfo->samples + offsets[j];
8996 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8997 VectorScale(lm, scale, c);
8998 if (surface->lightmapinfo->styles[1] != 255)
9000 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9002 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9003 VectorMA(c, scale, lm, c);
9004 if (surface->lightmapinfo->styles[2] != 255)
9007 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9008 VectorMA(c, scale, lm, c);
9009 if (surface->lightmapinfo->styles[3] != 255)
9012 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9013 VectorMA(c, scale, lm, c);
9020 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);
9026 for (j = 0;j < surfacenumvertices;j++)
9028 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9035 // if vertices are deformed (sprite flares and things in maps, possibly
9036 // water waves, bulges and other deformations), modify the copied vertices
9038 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9040 switch (deform->deform)
9043 case Q3DEFORM_PROJECTIONSHADOW:
9044 case Q3DEFORM_TEXT0:
9045 case Q3DEFORM_TEXT1:
9046 case Q3DEFORM_TEXT2:
9047 case Q3DEFORM_TEXT3:
9048 case Q3DEFORM_TEXT4:
9049 case Q3DEFORM_TEXT5:
9050 case Q3DEFORM_TEXT6:
9051 case Q3DEFORM_TEXT7:
9054 case Q3DEFORM_AUTOSPRITE:
9055 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9056 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9057 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9058 VectorNormalize(newforward);
9059 VectorNormalize(newright);
9060 VectorNormalize(newup);
9061 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9062 // rsurface.batchvertex3f_vertexbuffer = NULL;
9063 // rsurface.batchvertex3f_bufferoffset = 0;
9064 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9065 // rsurface.batchsvector3f_vertexbuffer = NULL;
9066 // rsurface.batchsvector3f_bufferoffset = 0;
9067 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9068 // rsurface.batchtvector3f_vertexbuffer = NULL;
9069 // rsurface.batchtvector3f_bufferoffset = 0;
9070 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9071 // rsurface.batchnormal3f_vertexbuffer = NULL;
9072 // rsurface.batchnormal3f_bufferoffset = 0;
9073 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9074 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9075 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9076 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9077 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);
9078 // a single autosprite surface can contain multiple sprites...
9079 for (j = 0;j < batchnumvertices - 3;j += 4)
9081 VectorClear(center);
9082 for (i = 0;i < 4;i++)
9083 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9084 VectorScale(center, 0.25f, center);
9085 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9086 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9087 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9088 for (i = 0;i < 4;i++)
9090 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9091 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9094 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9095 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9096 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);
9098 case Q3DEFORM_AUTOSPRITE2:
9099 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9100 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9101 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9102 VectorNormalize(newforward);
9103 VectorNormalize(newright);
9104 VectorNormalize(newup);
9105 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9106 // rsurface.batchvertex3f_vertexbuffer = NULL;
9107 // rsurface.batchvertex3f_bufferoffset = 0;
9109 const float *v1, *v2;
9119 memset(shortest, 0, sizeof(shortest));
9120 // a single autosprite surface can contain multiple sprites...
9121 for (j = 0;j < batchnumvertices - 3;j += 4)
9123 VectorClear(center);
9124 for (i = 0;i < 4;i++)
9125 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9126 VectorScale(center, 0.25f, center);
9127 // find the two shortest edges, then use them to define the
9128 // axis vectors for rotating around the central axis
9129 for (i = 0;i < 6;i++)
9131 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9132 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9133 l = VectorDistance2(v1, v2);
9134 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9136 l += (1.0f / 1024.0f);
9137 if (shortest[0].length2 > l || i == 0)
9139 shortest[1] = shortest[0];
9140 shortest[0].length2 = l;
9141 shortest[0].v1 = v1;
9142 shortest[0].v2 = v2;
9144 else if (shortest[1].length2 > l || i == 1)
9146 shortest[1].length2 = l;
9147 shortest[1].v1 = v1;
9148 shortest[1].v2 = v2;
9151 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9152 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9153 // this calculates the right vector from the shortest edge
9154 // and the up vector from the edge midpoints
9155 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9156 VectorNormalize(right);
9157 VectorSubtract(end, start, up);
9158 VectorNormalize(up);
9159 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9160 VectorSubtract(rsurface.localvieworigin, center, forward);
9161 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9162 VectorNegate(forward, forward);
9163 VectorReflect(forward, 0, up, forward);
9164 VectorNormalize(forward);
9165 CrossProduct(up, forward, newright);
9166 VectorNormalize(newright);
9167 // rotate the quad around the up axis vector, this is made
9168 // especially easy by the fact we know the quad is flat,
9169 // so we only have to subtract the center position and
9170 // measure distance along the right vector, and then
9171 // multiply that by the newright vector and add back the
9173 // we also need to subtract the old position to undo the
9174 // displacement from the center, which we do with a
9175 // DotProduct, the subtraction/addition of center is also
9176 // optimized into DotProducts here
9177 l = DotProduct(right, center);
9178 for (i = 0;i < 4;i++)
9180 v1 = rsurface.batchvertex3f + 3*(j+i);
9181 f = DotProduct(right, v1) - l;
9182 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9186 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9188 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9189 // rsurface.batchnormal3f_vertexbuffer = NULL;
9190 // rsurface.batchnormal3f_bufferoffset = 0;
9191 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9193 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9195 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9196 // rsurface.batchsvector3f_vertexbuffer = NULL;
9197 // rsurface.batchsvector3f_bufferoffset = 0;
9198 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9199 // rsurface.batchtvector3f_vertexbuffer = NULL;
9200 // rsurface.batchtvector3f_bufferoffset = 0;
9201 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);
9204 case Q3DEFORM_NORMAL:
9205 // deform the normals to make reflections wavey
9206 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9207 rsurface.batchnormal3f_vertexbuffer = NULL;
9208 rsurface.batchnormal3f_bufferoffset = 0;
9209 for (j = 0;j < batchnumvertices;j++)
9212 float *normal = rsurface.batchnormal3f + 3*j;
9213 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9214 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9215 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9216 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9217 VectorNormalize(normal);
9219 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9221 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9222 // rsurface.batchsvector3f_vertexbuffer = NULL;
9223 // rsurface.batchsvector3f_bufferoffset = 0;
9224 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9225 // rsurface.batchtvector3f_vertexbuffer = NULL;
9226 // rsurface.batchtvector3f_bufferoffset = 0;
9227 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);
9231 // deform vertex array to make wavey water and flags and such
9232 waveparms[0] = deform->waveparms[0];
9233 waveparms[1] = deform->waveparms[1];
9234 waveparms[2] = deform->waveparms[2];
9235 waveparms[3] = deform->waveparms[3];
9236 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9237 break; // if wavefunc is a nop, don't make a dynamic vertex array
9238 // this is how a divisor of vertex influence on deformation
9239 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9240 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9241 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9242 // rsurface.batchvertex3f_vertexbuffer = NULL;
9243 // rsurface.batchvertex3f_bufferoffset = 0;
9244 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9245 // rsurface.batchnormal3f_vertexbuffer = NULL;
9246 // rsurface.batchnormal3f_bufferoffset = 0;
9247 for (j = 0;j < batchnumvertices;j++)
9249 // if the wavefunc depends on time, evaluate it per-vertex
9252 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9253 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9255 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9257 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9258 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9259 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9261 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9262 // rsurface.batchsvector3f_vertexbuffer = NULL;
9263 // rsurface.batchsvector3f_bufferoffset = 0;
9264 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9265 // rsurface.batchtvector3f_vertexbuffer = NULL;
9266 // rsurface.batchtvector3f_bufferoffset = 0;
9267 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);
9270 case Q3DEFORM_BULGE:
9271 // deform vertex array to make the surface have moving bulges
9272 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9273 // rsurface.batchvertex3f_vertexbuffer = NULL;
9274 // rsurface.batchvertex3f_bufferoffset = 0;
9275 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9276 // rsurface.batchnormal3f_vertexbuffer = NULL;
9277 // rsurface.batchnormal3f_bufferoffset = 0;
9278 for (j = 0;j < batchnumvertices;j++)
9280 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9281 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9283 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9284 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9285 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9287 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9288 // rsurface.batchsvector3f_vertexbuffer = NULL;
9289 // rsurface.batchsvector3f_bufferoffset = 0;
9290 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9291 // rsurface.batchtvector3f_vertexbuffer = NULL;
9292 // rsurface.batchtvector3f_bufferoffset = 0;
9293 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);
9297 // deform vertex array
9298 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9299 break; // if wavefunc is a nop, don't make a dynamic vertex array
9300 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9301 VectorScale(deform->parms, scale, waveparms);
9302 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9303 // rsurface.batchvertex3f_vertexbuffer = NULL;
9304 // rsurface.batchvertex3f_bufferoffset = 0;
9305 for (j = 0;j < batchnumvertices;j++)
9306 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9311 // generate texcoords based on the chosen texcoord source
9312 switch(rsurface.texture->tcgen.tcgen)
9315 case Q3TCGEN_TEXTURE:
9317 case Q3TCGEN_LIGHTMAP:
9318 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9319 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9320 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9321 if (rsurface.batchtexcoordlightmap2f)
9322 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9324 case Q3TCGEN_VECTOR:
9325 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9326 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9327 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9328 for (j = 0;j < batchnumvertices;j++)
9330 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9331 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9334 case Q3TCGEN_ENVIRONMENT:
9335 // make environment reflections using a spheremap
9336 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9337 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9338 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9339 for (j = 0;j < batchnumvertices;j++)
9341 // identical to Q3A's method, but executed in worldspace so
9342 // carried models can be shiny too
9344 float viewer[3], d, reflected[3], worldreflected[3];
9346 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9347 // VectorNormalize(viewer);
9349 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9351 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9352 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9353 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9354 // note: this is proportinal to viewer, so we can normalize later
9356 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9357 VectorNormalize(worldreflected);
9359 // note: this sphere map only uses world x and z!
9360 // so positive and negative y will LOOK THE SAME.
9361 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9362 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9366 // the only tcmod that needs software vertex processing is turbulent, so
9367 // check for it here and apply the changes if needed
9368 // and we only support that as the first one
9369 // (handling a mixture of turbulent and other tcmods would be problematic
9370 // without punting it entirely to a software path)
9371 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9373 amplitude = rsurface.texture->tcmods[0].parms[1];
9374 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9375 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9376 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9377 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9378 for (j = 0;j < batchnumvertices;j++)
9380 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);
9381 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9385 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9387 // convert the modified arrays to vertex structs
9388 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9389 // rsurface.batchvertexmeshbuffer = NULL;
9390 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9391 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9392 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9393 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9394 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9395 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9396 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9398 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9400 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9401 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9404 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9405 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9406 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9407 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9408 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9409 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9410 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9411 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9412 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9416 void RSurf_DrawBatch(void)
9418 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9419 // through the pipeline, killing it earlier in the pipeline would have
9420 // per-surface overhead rather than per-batch overhead, so it's best to
9421 // reject it here, before it hits glDraw.
9422 if (rsurface.batchnumtriangles == 0)
9425 // batch debugging code
9426 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9432 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9433 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9436 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9438 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9440 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9441 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);
9448 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);
9451 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9453 // pick the closest matching water plane
9454 int planeindex, vertexindex, bestplaneindex = -1;
9458 r_waterstate_waterplane_t *p;
9459 qboolean prepared = false;
9461 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9463 if(p->camera_entity != rsurface.texture->camera_entity)
9468 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9470 if(rsurface.batchnumvertices == 0)
9473 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9475 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9476 d += fabs(PlaneDiff(vert, &p->plane));
9478 if (bestd > d || bestplaneindex < 0)
9481 bestplaneindex = planeindex;
9484 return bestplaneindex;
9485 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9486 // this situation though, as it might be better to render single larger
9487 // batches with useless stuff (backface culled for example) than to
9488 // render multiple smaller batches
9491 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9494 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9495 rsurface.passcolor4f_vertexbuffer = 0;
9496 rsurface.passcolor4f_bufferoffset = 0;
9497 for (i = 0;i < rsurface.batchnumvertices;i++)
9498 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9501 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9508 if (rsurface.passcolor4f)
9510 // generate color arrays
9511 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9512 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9513 rsurface.passcolor4f_vertexbuffer = 0;
9514 rsurface.passcolor4f_bufferoffset = 0;
9515 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)
9517 f = RSurf_FogVertex(v);
9526 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9527 rsurface.passcolor4f_vertexbuffer = 0;
9528 rsurface.passcolor4f_bufferoffset = 0;
9529 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9531 f = RSurf_FogVertex(v);
9540 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9547 if (!rsurface.passcolor4f)
9549 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9550 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9551 rsurface.passcolor4f_vertexbuffer = 0;
9552 rsurface.passcolor4f_bufferoffset = 0;
9553 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9555 f = RSurf_FogVertex(v);
9556 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9557 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9558 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9563 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9568 if (!rsurface.passcolor4f)
9570 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9571 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9572 rsurface.passcolor4f_vertexbuffer = 0;
9573 rsurface.passcolor4f_bufferoffset = 0;
9574 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9583 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9588 if (!rsurface.passcolor4f)
9590 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9591 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9592 rsurface.passcolor4f_vertexbuffer = 0;
9593 rsurface.passcolor4f_bufferoffset = 0;
9594 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9596 c2[0] = c[0] + r_refdef.scene.ambient;
9597 c2[1] = c[1] + r_refdef.scene.ambient;
9598 c2[2] = c[2] + r_refdef.scene.ambient;
9603 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9606 rsurface.passcolor4f = NULL;
9607 rsurface.passcolor4f_vertexbuffer = 0;
9608 rsurface.passcolor4f_bufferoffset = 0;
9609 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9610 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9611 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9612 GL_Color(r, g, b, a);
9613 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9617 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9619 // TODO: optimize applyfog && applycolor case
9620 // just apply fog if necessary, and tint the fog color array if necessary
9621 rsurface.passcolor4f = NULL;
9622 rsurface.passcolor4f_vertexbuffer = 0;
9623 rsurface.passcolor4f_bufferoffset = 0;
9624 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9625 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9626 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9627 GL_Color(r, g, b, a);
9631 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9634 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9635 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9636 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9637 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9638 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9639 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9640 GL_Color(r, g, b, a);
9644 static void RSurf_DrawBatch_GL11_ClampColor(void)
9649 if (!rsurface.passcolor4f)
9651 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9653 c2[0] = bound(0.0f, c1[0], 1.0f);
9654 c2[1] = bound(0.0f, c1[1], 1.0f);
9655 c2[2] = bound(0.0f, c1[2], 1.0f);
9656 c2[3] = bound(0.0f, c1[3], 1.0f);
9660 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9670 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9671 rsurface.passcolor4f_vertexbuffer = 0;
9672 rsurface.passcolor4f_bufferoffset = 0;
9673 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)
9675 f = -DotProduct(r_refdef.view.forward, n);
9677 f = f * 0.85 + 0.15; // work around so stuff won't get black
9678 f *= r_refdef.lightmapintensity;
9679 Vector4Set(c, f, f, f, 1);
9683 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9685 RSurf_DrawBatch_GL11_ApplyFakeLight();
9686 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9687 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9688 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9689 GL_Color(r, g, b, a);
9693 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9701 vec3_t ambientcolor;
9702 vec3_t diffusecolor;
9706 VectorCopy(rsurface.modellight_lightdir, lightdir);
9707 f = 0.5f * r_refdef.lightmapintensity;
9708 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9709 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9710 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9711 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9712 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9713 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9715 if (VectorLength2(diffusecolor) > 0)
9717 // q3-style directional shading
9718 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9719 rsurface.passcolor4f_vertexbuffer = 0;
9720 rsurface.passcolor4f_bufferoffset = 0;
9721 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)
9723 if ((f = DotProduct(n, lightdir)) > 0)
9724 VectorMA(ambientcolor, f, diffusecolor, c);
9726 VectorCopy(ambientcolor, c);
9733 *applycolor = false;
9737 *r = ambientcolor[0];
9738 *g = ambientcolor[1];
9739 *b = ambientcolor[2];
9740 rsurface.passcolor4f = NULL;
9741 rsurface.passcolor4f_vertexbuffer = 0;
9742 rsurface.passcolor4f_bufferoffset = 0;
9746 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9748 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9749 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9750 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9751 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9752 GL_Color(r, g, b, a);
9756 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9764 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9765 rsurface.passcolor4f_vertexbuffer = 0;
9766 rsurface.passcolor4f_bufferoffset = 0;
9768 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9770 f = 1 - RSurf_FogVertex(v);
9778 void RSurf_SetupDepthAndCulling(void)
9780 // submodels are biased to avoid z-fighting with world surfaces that they
9781 // may be exactly overlapping (avoids z-fighting artifacts on certain
9782 // doors and things in Quake maps)
9783 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9784 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9785 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9786 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9789 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9791 // transparent sky would be ridiculous
9792 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9794 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9795 skyrenderlater = true;
9796 RSurf_SetupDepthAndCulling();
9798 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9799 // skymasking on them, and Quake3 never did sky masking (unlike
9800 // software Quake and software Quake2), so disable the sky masking
9801 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9802 // and skymasking also looks very bad when noclipping outside the
9803 // level, so don't use it then either.
9804 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9806 R_Mesh_ResetTextureState();
9807 if (skyrendermasked)
9809 R_SetupShader_DepthOrShadow(false);
9810 // depth-only (masking)
9811 GL_ColorMask(0,0,0,0);
9812 // just to make sure that braindead drivers don't draw
9813 // anything despite that colormask...
9814 GL_BlendFunc(GL_ZERO, GL_ONE);
9815 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816 if (rsurface.batchvertex3fbuffer)
9817 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9819 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9823 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9825 GL_BlendFunc(GL_ONE, GL_ZERO);
9826 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9827 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9828 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9831 if (skyrendermasked)
9832 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9834 R_Mesh_ResetTextureState();
9835 GL_Color(1, 1, 1, 1);
9838 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9839 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9840 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9842 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9846 // render screenspace normalmap to texture
9848 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9852 // bind lightmap texture
9854 // water/refraction/reflection/camera surfaces have to be handled specially
9855 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9857 int start, end, startplaneindex;
9858 for (start = 0;start < texturenumsurfaces;start = end)
9860 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9861 if(startplaneindex < 0)
9863 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9864 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9868 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9870 // now that we have a batch using the same planeindex, render it
9871 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9873 // render water or distortion background
9875 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);
9877 // blend surface on top
9878 GL_DepthMask(false);
9879 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9882 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9884 // render surface with reflection texture as input
9885 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9886 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);
9893 // render surface batch normally
9894 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9895 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);
9899 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9901 // OpenGL 1.3 path - anything not completely ancient
9902 qboolean applycolor;
9905 const texturelayer_t *layer;
9906 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);
9907 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9909 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9912 int layertexrgbscale;
9913 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9915 if (layerindex == 0)
9919 GL_AlphaTest(false);
9920 GL_DepthFunc(GL_EQUAL);
9923 GL_DepthMask(layer->depthmask && writedepth);
9924 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9925 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9927 layertexrgbscale = 4;
9928 VectorScale(layer->color, 0.25f, layercolor);
9930 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9932 layertexrgbscale = 2;
9933 VectorScale(layer->color, 0.5f, layercolor);
9937 layertexrgbscale = 1;
9938 VectorScale(layer->color, 1.0f, layercolor);
9940 layercolor[3] = layer->color[3];
9941 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9942 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9943 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9944 switch (layer->type)
9946 case TEXTURELAYERTYPE_LITTEXTURE:
9947 // single-pass lightmapped texture with 2x rgbscale
9948 R_Mesh_TexBind(0, r_texture_white);
9949 R_Mesh_TexMatrix(0, NULL);
9950 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9951 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9952 R_Mesh_TexBind(1, layer->texture);
9953 R_Mesh_TexMatrix(1, &layer->texmatrix);
9954 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9955 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9956 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9957 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9958 else if (FAKELIGHT_ENABLED)
9959 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9960 else if (rsurface.uselightmaptexture)
9961 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9963 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9965 case TEXTURELAYERTYPE_TEXTURE:
9966 // singletexture unlit texture with transparency support
9967 R_Mesh_TexBind(0, layer->texture);
9968 R_Mesh_TexMatrix(0, &layer->texmatrix);
9969 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9970 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9971 R_Mesh_TexBind(1, 0);
9972 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9973 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9975 case TEXTURELAYERTYPE_FOG:
9976 // singletexture fogging
9979 R_Mesh_TexBind(0, layer->texture);
9980 R_Mesh_TexMatrix(0, &layer->texmatrix);
9981 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9982 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9986 R_Mesh_TexBind(0, 0);
9987 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9989 R_Mesh_TexBind(1, 0);
9990 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9991 // generate a color array for the fog pass
9992 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9993 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9997 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10000 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10002 GL_DepthFunc(GL_LEQUAL);
10003 GL_AlphaTest(false);
10007 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10009 // OpenGL 1.1 - crusty old voodoo path
10012 const texturelayer_t *layer;
10013 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);
10014 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10016 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10018 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10020 if (layerindex == 0)
10021 GL_AlphaTest(true);
10024 GL_AlphaTest(false);
10025 GL_DepthFunc(GL_EQUAL);
10028 GL_DepthMask(layer->depthmask && writedepth);
10029 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10030 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10031 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10032 switch (layer->type)
10034 case TEXTURELAYERTYPE_LITTEXTURE:
10035 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10037 // two-pass lit texture with 2x rgbscale
10038 // first the lightmap pass
10039 R_Mesh_TexBind(0, r_texture_white);
10040 R_Mesh_TexMatrix(0, NULL);
10041 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10042 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10043 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10044 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10045 else if (FAKELIGHT_ENABLED)
10046 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10047 else if (rsurface.uselightmaptexture)
10048 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10050 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10051 // then apply the texture to it
10052 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10053 R_Mesh_TexBind(0, layer->texture);
10054 R_Mesh_TexMatrix(0, &layer->texmatrix);
10055 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057 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);
10061 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10062 R_Mesh_TexBind(0, layer->texture);
10063 R_Mesh_TexMatrix(0, &layer->texmatrix);
10064 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10065 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10066 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10067 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);
10069 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);
10072 case TEXTURELAYERTYPE_TEXTURE:
10073 // singletexture unlit texture with transparency support
10074 R_Mesh_TexBind(0, layer->texture);
10075 R_Mesh_TexMatrix(0, &layer->texmatrix);
10076 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10077 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10078 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);
10080 case TEXTURELAYERTYPE_FOG:
10081 // singletexture fogging
10082 if (layer->texture)
10084 R_Mesh_TexBind(0, layer->texture);
10085 R_Mesh_TexMatrix(0, &layer->texmatrix);
10086 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10087 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10091 R_Mesh_TexBind(0, 0);
10092 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10094 // generate a color array for the fog pass
10095 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10096 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10100 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10103 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10105 GL_DepthFunc(GL_LEQUAL);
10106 GL_AlphaTest(false);
10110 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10114 r_vertexgeneric_t *batchvertex;
10117 // R_Mesh_ResetTextureState();
10118 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10120 if(rsurface.texture && rsurface.texture->currentskinframe)
10122 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10123 c[3] *= rsurface.texture->currentalpha;
10133 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10135 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10136 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10137 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10140 // brighten it up (as texture value 127 means "unlit")
10141 c[0] *= 2 * r_refdef.view.colorscale;
10142 c[1] *= 2 * r_refdef.view.colorscale;
10143 c[2] *= 2 * r_refdef.view.colorscale;
10145 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10146 c[3] *= r_wateralpha.value;
10148 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10150 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10151 GL_DepthMask(false);
10153 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10155 GL_BlendFunc(GL_ONE, GL_ONE);
10156 GL_DepthMask(false);
10158 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10160 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10161 GL_DepthMask(false);
10163 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10165 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10166 GL_DepthMask(false);
10170 GL_BlendFunc(GL_ONE, GL_ZERO);
10171 GL_DepthMask(writedepth);
10174 if (r_showsurfaces.integer == 3)
10176 rsurface.passcolor4f = NULL;
10178 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10180 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10182 rsurface.passcolor4f = NULL;
10183 rsurface.passcolor4f_vertexbuffer = 0;
10184 rsurface.passcolor4f_bufferoffset = 0;
10186 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10188 qboolean applycolor = true;
10191 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10193 r_refdef.lightmapintensity = 1;
10194 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10195 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10197 else if (FAKELIGHT_ENABLED)
10199 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10201 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10202 RSurf_DrawBatch_GL11_ApplyFakeLight();
10203 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10207 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10209 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10210 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10211 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10214 if(!rsurface.passcolor4f)
10215 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10217 RSurf_DrawBatch_GL11_ApplyAmbient();
10218 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10219 if(r_refdef.fogenabled)
10220 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10221 RSurf_DrawBatch_GL11_ClampColor();
10223 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10224 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10227 else if (!r_refdef.view.showdebug)
10229 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10230 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10231 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10233 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10234 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10236 R_Mesh_PrepareVertices_Generic_Unlock();
10239 else if (r_showsurfaces.integer == 4)
10241 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10242 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10243 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10245 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10246 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10247 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10249 R_Mesh_PrepareVertices_Generic_Unlock();
10252 else if (r_showsurfaces.integer == 2)
10255 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10256 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10257 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10259 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10260 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10261 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10262 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10263 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10264 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10265 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10267 R_Mesh_PrepareVertices_Generic_Unlock();
10268 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10272 int texturesurfaceindex;
10274 const msurface_t *surface;
10275 float surfacecolor4f[4];
10276 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10277 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10279 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10281 surface = texturesurfacelist[texturesurfaceindex];
10282 k = (int)(((size_t)surface) / sizeof(msurface_t));
10283 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10284 for (j = 0;j < surface->num_vertices;j++)
10286 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10287 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10291 R_Mesh_PrepareVertices_Generic_Unlock();
10296 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10299 RSurf_SetupDepthAndCulling();
10300 if (r_showsurfaces.integer)
10302 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10305 switch (vid.renderpath)
10307 case RENDERPATH_GL20:
10308 case RENDERPATH_D3D9:
10309 case RENDERPATH_D3D10:
10310 case RENDERPATH_D3D11:
10311 case RENDERPATH_SOFT:
10312 case RENDERPATH_GLES2:
10313 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10315 case RENDERPATH_GL13:
10316 case RENDERPATH_GLES1:
10317 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10319 case RENDERPATH_GL11:
10320 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10326 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10329 RSurf_SetupDepthAndCulling();
10330 if (r_showsurfaces.integer)
10332 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10335 switch (vid.renderpath)
10337 case RENDERPATH_GL20:
10338 case RENDERPATH_D3D9:
10339 case RENDERPATH_D3D10:
10340 case RENDERPATH_D3D11:
10341 case RENDERPATH_SOFT:
10342 case RENDERPATH_GLES2:
10343 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10345 case RENDERPATH_GL13:
10346 case RENDERPATH_GLES1:
10347 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10349 case RENDERPATH_GL11:
10350 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10356 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10359 int texturenumsurfaces, endsurface;
10360 texture_t *texture;
10361 const msurface_t *surface;
10362 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10364 // if the model is static it doesn't matter what value we give for
10365 // wantnormals and wanttangents, so this logic uses only rules applicable
10366 // to a model, knowing that they are meaningless otherwise
10367 if (ent == r_refdef.scene.worldentity)
10368 RSurf_ActiveWorldEntity();
10369 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10370 RSurf_ActiveModelEntity(ent, false, false, false);
10373 switch (vid.renderpath)
10375 case RENDERPATH_GL20:
10376 case RENDERPATH_D3D9:
10377 case RENDERPATH_D3D10:
10378 case RENDERPATH_D3D11:
10379 case RENDERPATH_SOFT:
10380 case RENDERPATH_GLES2:
10381 RSurf_ActiveModelEntity(ent, true, true, false);
10383 case RENDERPATH_GL11:
10384 case RENDERPATH_GL13:
10385 case RENDERPATH_GLES1:
10386 RSurf_ActiveModelEntity(ent, true, false, false);
10391 if (r_transparentdepthmasking.integer)
10393 qboolean setup = false;
10394 for (i = 0;i < numsurfaces;i = j)
10397 surface = rsurface.modelsurfaces + surfacelist[i];
10398 texture = surface->texture;
10399 rsurface.texture = R_GetCurrentTexture(texture);
10400 rsurface.lightmaptexture = NULL;
10401 rsurface.deluxemaptexture = NULL;
10402 rsurface.uselightmaptexture = false;
10403 // scan ahead until we find a different texture
10404 endsurface = min(i + 1024, numsurfaces);
10405 texturenumsurfaces = 0;
10406 texturesurfacelist[texturenumsurfaces++] = surface;
10407 for (;j < endsurface;j++)
10409 surface = rsurface.modelsurfaces + surfacelist[j];
10410 if (texture != surface->texture)
10412 texturesurfacelist[texturenumsurfaces++] = surface;
10414 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10416 // render the range of surfaces as depth
10420 GL_ColorMask(0,0,0,0);
10422 GL_DepthTest(true);
10423 GL_BlendFunc(GL_ONE, GL_ZERO);
10424 GL_DepthMask(true);
10425 // R_Mesh_ResetTextureState();
10426 R_SetupShader_DepthOrShadow(false);
10428 RSurf_SetupDepthAndCulling();
10429 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10430 if (rsurface.batchvertex3fbuffer)
10431 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10433 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10437 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10440 for (i = 0;i < numsurfaces;i = j)
10443 surface = rsurface.modelsurfaces + surfacelist[i];
10444 texture = surface->texture;
10445 rsurface.texture = R_GetCurrentTexture(texture);
10446 // scan ahead until we find a different texture
10447 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10448 texturenumsurfaces = 0;
10449 texturesurfacelist[texturenumsurfaces++] = surface;
10450 if(FAKELIGHT_ENABLED)
10452 rsurface.lightmaptexture = NULL;
10453 rsurface.deluxemaptexture = NULL;
10454 rsurface.uselightmaptexture = false;
10455 for (;j < endsurface;j++)
10457 surface = rsurface.modelsurfaces + surfacelist[j];
10458 if (texture != surface->texture)
10460 texturesurfacelist[texturenumsurfaces++] = surface;
10465 rsurface.lightmaptexture = surface->lightmaptexture;
10466 rsurface.deluxemaptexture = surface->deluxemaptexture;
10467 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10468 for (;j < endsurface;j++)
10470 surface = rsurface.modelsurfaces + surfacelist[j];
10471 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10473 texturesurfacelist[texturenumsurfaces++] = surface;
10476 // render the range of surfaces
10477 if (ent == r_refdef.scene.worldentity)
10478 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10480 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10482 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10485 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10487 // transparent surfaces get pushed off into the transparent queue
10488 int surfacelistindex;
10489 const msurface_t *surface;
10490 vec3_t tempcenter, center;
10491 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10493 surface = texturesurfacelist[surfacelistindex];
10494 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10495 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10496 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10497 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10498 if (queueentity->transparent_offset) // transparent offset
10500 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10501 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10502 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10504 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10508 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10510 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10512 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10514 RSurf_SetupDepthAndCulling();
10515 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10516 if (rsurface.batchvertex3fbuffer)
10517 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10519 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10523 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10525 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10528 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10531 if (!rsurface.texture->currentnumlayers)
10533 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10534 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10536 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10538 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10539 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10540 else if (!rsurface.texture->currentnumlayers)
10542 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10544 // in the deferred case, transparent surfaces were queued during prepass
10545 if (!r_shadow_usingdeferredprepass)
10546 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10550 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10551 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10556 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10559 texture_t *texture;
10560 R_FrameData_SetMark();
10561 // break the surface list down into batches by texture and use of lightmapping
10562 for (i = 0;i < numsurfaces;i = j)
10565 // texture is the base texture pointer, rsurface.texture is the
10566 // current frame/skin the texture is directing us to use (for example
10567 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10568 // use skin 1 instead)
10569 texture = surfacelist[i]->texture;
10570 rsurface.texture = R_GetCurrentTexture(texture);
10571 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10573 // if this texture is not the kind we want, skip ahead to the next one
10574 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10578 if(FAKELIGHT_ENABLED || depthonly || prepass)
10580 rsurface.lightmaptexture = NULL;
10581 rsurface.deluxemaptexture = NULL;
10582 rsurface.uselightmaptexture = false;
10583 // simply scan ahead until we find a different texture or lightmap state
10584 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10589 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10590 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10591 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10592 // simply scan ahead until we find a different texture or lightmap state
10593 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10596 // render the range of surfaces
10597 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10599 R_FrameData_ReturnToMark();
10602 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10606 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10609 if (!rsurface.texture->currentnumlayers)
10611 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10612 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10614 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10616 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10617 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10618 else if (!rsurface.texture->currentnumlayers)
10620 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10622 // in the deferred case, transparent surfaces were queued during prepass
10623 if (!r_shadow_usingdeferredprepass)
10624 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10628 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10629 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10634 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10637 texture_t *texture;
10638 R_FrameData_SetMark();
10639 // break the surface list down into batches by texture and use of lightmapping
10640 for (i = 0;i < numsurfaces;i = j)
10643 // texture is the base texture pointer, rsurface.texture is the
10644 // current frame/skin the texture is directing us to use (for example
10645 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10646 // use skin 1 instead)
10647 texture = surfacelist[i]->texture;
10648 rsurface.texture = R_GetCurrentTexture(texture);
10649 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10651 // if this texture is not the kind we want, skip ahead to the next one
10652 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10656 if(FAKELIGHT_ENABLED || depthonly || prepass)
10658 rsurface.lightmaptexture = NULL;
10659 rsurface.deluxemaptexture = NULL;
10660 rsurface.uselightmaptexture = false;
10661 // simply scan ahead until we find a different texture or lightmap state
10662 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10667 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10668 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10669 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10670 // simply scan ahead until we find a different texture or lightmap state
10671 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10674 // render the range of surfaces
10675 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10677 R_FrameData_ReturnToMark();
10680 float locboxvertex3f[6*4*3] =
10682 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10683 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10684 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10685 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10686 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10687 1,0,0, 0,0,0, 0,1,0, 1,1,0
10690 unsigned short locboxelements[6*2*3] =
10695 12,13,14, 12,14,15,
10696 16,17,18, 16,18,19,
10700 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10703 cl_locnode_t *loc = (cl_locnode_t *)ent;
10705 float vertex3f[6*4*3];
10707 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10708 GL_DepthMask(false);
10709 GL_DepthRange(0, 1);
10710 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10711 GL_DepthTest(true);
10712 GL_CullFace(GL_NONE);
10713 R_EntityMatrix(&identitymatrix);
10715 // R_Mesh_ResetTextureState();
10717 i = surfacelist[0];
10718 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10719 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10720 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10721 surfacelist[0] < 0 ? 0.5f : 0.125f);
10723 if (VectorCompare(loc->mins, loc->maxs))
10725 VectorSet(size, 2, 2, 2);
10726 VectorMA(loc->mins, -0.5f, size, mins);
10730 VectorCopy(loc->mins, mins);
10731 VectorSubtract(loc->maxs, loc->mins, size);
10734 for (i = 0;i < 6*4*3;)
10735 for (j = 0;j < 3;j++, i++)
10736 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10738 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10739 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10740 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10743 void R_DrawLocs(void)
10746 cl_locnode_t *loc, *nearestloc;
10748 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10749 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10751 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10752 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10756 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10758 if (decalsystem->decals)
10759 Mem_Free(decalsystem->decals);
10760 memset(decalsystem, 0, sizeof(*decalsystem));
10763 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)
10766 tridecal_t *decals;
10769 // expand or initialize the system
10770 if (decalsystem->maxdecals <= decalsystem->numdecals)
10772 decalsystem_t old = *decalsystem;
10773 qboolean useshortelements;
10774 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10775 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10776 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)));
10777 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10778 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10779 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10780 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10781 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10782 if (decalsystem->numdecals)
10783 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10785 Mem_Free(old.decals);
10786 for (i = 0;i < decalsystem->maxdecals*3;i++)
10787 decalsystem->element3i[i] = i;
10788 if (useshortelements)
10789 for (i = 0;i < decalsystem->maxdecals*3;i++)
10790 decalsystem->element3s[i] = i;
10793 // grab a decal and search for another free slot for the next one
10794 decals = decalsystem->decals;
10795 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10796 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10798 decalsystem->freedecal = i;
10799 if (decalsystem->numdecals <= i)
10800 decalsystem->numdecals = i + 1;
10802 // initialize the decal
10804 decal->triangleindex = triangleindex;
10805 decal->surfaceindex = surfaceindex;
10806 decal->decalsequence = decalsequence;
10807 decal->color4f[0][0] = c0[0];
10808 decal->color4f[0][1] = c0[1];
10809 decal->color4f[0][2] = c0[2];
10810 decal->color4f[0][3] = 1;
10811 decal->color4f[1][0] = c1[0];
10812 decal->color4f[1][1] = c1[1];
10813 decal->color4f[1][2] = c1[2];
10814 decal->color4f[1][3] = 1;
10815 decal->color4f[2][0] = c2[0];
10816 decal->color4f[2][1] = c2[1];
10817 decal->color4f[2][2] = c2[2];
10818 decal->color4f[2][3] = 1;
10819 decal->vertex3f[0][0] = v0[0];
10820 decal->vertex3f[0][1] = v0[1];
10821 decal->vertex3f[0][2] = v0[2];
10822 decal->vertex3f[1][0] = v1[0];
10823 decal->vertex3f[1][1] = v1[1];
10824 decal->vertex3f[1][2] = v1[2];
10825 decal->vertex3f[2][0] = v2[0];
10826 decal->vertex3f[2][1] = v2[1];
10827 decal->vertex3f[2][2] = v2[2];
10828 decal->texcoord2f[0][0] = t0[0];
10829 decal->texcoord2f[0][1] = t0[1];
10830 decal->texcoord2f[1][0] = t1[0];
10831 decal->texcoord2f[1][1] = t1[1];
10832 decal->texcoord2f[2][0] = t2[0];
10833 decal->texcoord2f[2][1] = t2[1];
10834 TriangleNormal(v0, v1, v2, decal->plane);
10835 VectorNormalize(decal->plane);
10836 decal->plane[3] = DotProduct(v0, decal->plane);
10839 extern cvar_t cl_decals_bias;
10840 extern cvar_t cl_decals_models;
10841 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10842 // baseparms, parms, temps
10843 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)
10848 const float *vertex3f;
10849 const float *normal3f;
10851 float points[2][9][3];
10858 e = rsurface.modelelement3i + 3*triangleindex;
10860 vertex3f = rsurface.modelvertex3f;
10861 normal3f = rsurface.modelnormal3f;
10865 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10867 index = 3*e[cornerindex];
10868 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10873 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10875 index = 3*e[cornerindex];
10876 VectorCopy(vertex3f + index, v[cornerindex]);
10881 //TriangleNormal(v[0], v[1], v[2], normal);
10882 //if (DotProduct(normal, localnormal) < 0.0f)
10884 // clip by each of the box planes formed from the projection matrix
10885 // if anything survives, we emit the decal
10886 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]);
10889 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]);
10892 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]);
10895 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]);
10898 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]);
10901 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]);
10904 // some part of the triangle survived, so we have to accept it...
10907 // dynamic always uses the original triangle
10909 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10911 index = 3*e[cornerindex];
10912 VectorCopy(vertex3f + index, v[cornerindex]);
10915 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10917 // convert vertex positions to texcoords
10918 Matrix4x4_Transform(projection, v[cornerindex], temp);
10919 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10920 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10921 // calculate distance fade from the projection origin
10922 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10923 f = bound(0.0f, f, 1.0f);
10924 c[cornerindex][0] = r * f;
10925 c[cornerindex][1] = g * f;
10926 c[cornerindex][2] = b * f;
10927 c[cornerindex][3] = 1.0f;
10928 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10931 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);
10933 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10934 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);
10936 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)
10938 matrix4x4_t projection;
10939 decalsystem_t *decalsystem;
10942 const msurface_t *surface;
10943 const msurface_t *surfaces;
10944 const int *surfacelist;
10945 const texture_t *texture;
10947 int numsurfacelist;
10948 int surfacelistindex;
10951 float localorigin[3];
10952 float localnormal[3];
10953 float localmins[3];
10954 float localmaxs[3];
10957 float planes[6][4];
10960 int bih_triangles_count;
10961 int bih_triangles[256];
10962 int bih_surfaces[256];
10964 decalsystem = &ent->decalsystem;
10965 model = ent->model;
10966 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10968 R_DecalSystem_Reset(&ent->decalsystem);
10972 if (!model->brush.data_leafs && !cl_decals_models.integer)
10974 if (decalsystem->model)
10975 R_DecalSystem_Reset(decalsystem);
10979 if (decalsystem->model != model)
10980 R_DecalSystem_Reset(decalsystem);
10981 decalsystem->model = model;
10983 RSurf_ActiveModelEntity(ent, true, false, false);
10985 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10986 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10987 VectorNormalize(localnormal);
10988 localsize = worldsize*rsurface.inversematrixscale;
10989 localmins[0] = localorigin[0] - localsize;
10990 localmins[1] = localorigin[1] - localsize;
10991 localmins[2] = localorigin[2] - localsize;
10992 localmaxs[0] = localorigin[0] + localsize;
10993 localmaxs[1] = localorigin[1] + localsize;
10994 localmaxs[2] = localorigin[2] + localsize;
10996 //VectorCopy(localnormal, planes[4]);
10997 //VectorVectors(planes[4], planes[2], planes[0]);
10998 AnglesFromVectors(angles, localnormal, NULL, false);
10999 AngleVectors(angles, planes[0], planes[2], planes[4]);
11000 VectorNegate(planes[0], planes[1]);
11001 VectorNegate(planes[2], planes[3]);
11002 VectorNegate(planes[4], planes[5]);
11003 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11004 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11005 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11006 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11007 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11008 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11013 matrix4x4_t forwardprojection;
11014 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11015 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11020 float projectionvector[4][3];
11021 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11022 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11023 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11024 projectionvector[0][0] = planes[0][0] * ilocalsize;
11025 projectionvector[0][1] = planes[1][0] * ilocalsize;
11026 projectionvector[0][2] = planes[2][0] * ilocalsize;
11027 projectionvector[1][0] = planes[0][1] * ilocalsize;
11028 projectionvector[1][1] = planes[1][1] * ilocalsize;
11029 projectionvector[1][2] = planes[2][1] * ilocalsize;
11030 projectionvector[2][0] = planes[0][2] * ilocalsize;
11031 projectionvector[2][1] = planes[1][2] * ilocalsize;
11032 projectionvector[2][2] = planes[2][2] * ilocalsize;
11033 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11034 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11035 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11036 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11040 dynamic = model->surfmesh.isanimated;
11041 numsurfacelist = model->nummodelsurfaces;
11042 surfacelist = model->sortedmodelsurfaces;
11043 surfaces = model->data_surfaces;
11046 bih_triangles_count = -1;
11049 if(model->render_bih.numleafs)
11050 bih = &model->render_bih;
11051 else if(model->collision_bih.numleafs)
11052 bih = &model->collision_bih;
11055 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11056 if(bih_triangles_count == 0)
11058 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11060 if(bih_triangles_count > 0)
11062 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11064 surfaceindex = bih_surfaces[triangleindex];
11065 surface = surfaces + surfaceindex;
11066 texture = surface->texture;
11067 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11069 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11071 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11076 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11078 surfaceindex = surfacelist[surfacelistindex];
11079 surface = surfaces + surfaceindex;
11080 // check cull box first because it rejects more than any other check
11081 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11083 // skip transparent surfaces
11084 texture = surface->texture;
11085 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11087 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11089 numtriangles = surface->num_triangles;
11090 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11091 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11096 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11097 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)
11099 int renderentityindex;
11100 float worldmins[3];
11101 float worldmaxs[3];
11102 entity_render_t *ent;
11104 if (!cl_decals_newsystem.integer)
11107 worldmins[0] = worldorigin[0] - worldsize;
11108 worldmins[1] = worldorigin[1] - worldsize;
11109 worldmins[2] = worldorigin[2] - worldsize;
11110 worldmaxs[0] = worldorigin[0] + worldsize;
11111 worldmaxs[1] = worldorigin[1] + worldsize;
11112 worldmaxs[2] = worldorigin[2] + worldsize;
11114 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11116 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11118 ent = r_refdef.scene.entities[renderentityindex];
11119 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11122 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11126 typedef struct r_decalsystem_splatqueue_s
11128 vec3_t worldorigin;
11129 vec3_t worldnormal;
11135 r_decalsystem_splatqueue_t;
11137 int r_decalsystem_numqueued = 0;
11138 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11140 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)
11142 r_decalsystem_splatqueue_t *queue;
11144 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11147 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11148 VectorCopy(worldorigin, queue->worldorigin);
11149 VectorCopy(worldnormal, queue->worldnormal);
11150 Vector4Set(queue->color, r, g, b, a);
11151 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11152 queue->worldsize = worldsize;
11153 queue->decalsequence = cl.decalsequence++;
11156 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11159 r_decalsystem_splatqueue_t *queue;
11161 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11162 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);
11163 r_decalsystem_numqueued = 0;
11166 extern cvar_t cl_decals_max;
11167 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11170 decalsystem_t *decalsystem = &ent->decalsystem;
11177 if (!decalsystem->numdecals)
11180 if (r_showsurfaces.integer)
11183 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11185 R_DecalSystem_Reset(decalsystem);
11189 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11190 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11192 if (decalsystem->lastupdatetime)
11193 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11196 decalsystem->lastupdatetime = r_refdef.scene.time;
11197 decal = decalsystem->decals;
11198 numdecals = decalsystem->numdecals;
11200 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11202 if (decal->color4f[0][3])
11204 decal->lived += frametime;
11205 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11207 memset(decal, 0, sizeof(*decal));
11208 if (decalsystem->freedecal > i)
11209 decalsystem->freedecal = i;
11213 decal = decalsystem->decals;
11214 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11217 // collapse the array by shuffling the tail decals into the gaps
11220 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11221 decalsystem->freedecal++;
11222 if (decalsystem->freedecal == numdecals)
11224 decal[decalsystem->freedecal] = decal[--numdecals];
11227 decalsystem->numdecals = numdecals;
11229 if (numdecals <= 0)
11231 // if there are no decals left, reset decalsystem
11232 R_DecalSystem_Reset(decalsystem);
11236 extern skinframe_t *decalskinframe;
11237 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11240 decalsystem_t *decalsystem = &ent->decalsystem;
11249 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11252 numdecals = decalsystem->numdecals;
11256 if (r_showsurfaces.integer)
11259 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11261 R_DecalSystem_Reset(decalsystem);
11265 // if the model is static it doesn't matter what value we give for
11266 // wantnormals and wanttangents, so this logic uses only rules applicable
11267 // to a model, knowing that they are meaningless otherwise
11268 if (ent == r_refdef.scene.worldentity)
11269 RSurf_ActiveWorldEntity();
11271 RSurf_ActiveModelEntity(ent, false, false, false);
11273 decalsystem->lastupdatetime = r_refdef.scene.time;
11274 decal = decalsystem->decals;
11276 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11278 // update vertex positions for animated models
11279 v3f = decalsystem->vertex3f;
11280 c4f = decalsystem->color4f;
11281 t2f = decalsystem->texcoord2f;
11282 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11284 if (!decal->color4f[0][3])
11287 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11291 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11294 // update color values for fading decals
11295 if (decal->lived >= cl_decals_time.value)
11296 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11300 c4f[ 0] = decal->color4f[0][0] * alpha;
11301 c4f[ 1] = decal->color4f[0][1] * alpha;
11302 c4f[ 2] = decal->color4f[0][2] * alpha;
11304 c4f[ 4] = decal->color4f[1][0] * alpha;
11305 c4f[ 5] = decal->color4f[1][1] * alpha;
11306 c4f[ 6] = decal->color4f[1][2] * alpha;
11308 c4f[ 8] = decal->color4f[2][0] * alpha;
11309 c4f[ 9] = decal->color4f[2][1] * alpha;
11310 c4f[10] = decal->color4f[2][2] * alpha;
11313 t2f[0] = decal->texcoord2f[0][0];
11314 t2f[1] = decal->texcoord2f[0][1];
11315 t2f[2] = decal->texcoord2f[1][0];
11316 t2f[3] = decal->texcoord2f[1][1];
11317 t2f[4] = decal->texcoord2f[2][0];
11318 t2f[5] = decal->texcoord2f[2][1];
11320 // update vertex positions for animated models
11321 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11323 e = rsurface.modelelement3i + 3*decal->triangleindex;
11324 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11325 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11326 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11330 VectorCopy(decal->vertex3f[0], v3f);
11331 VectorCopy(decal->vertex3f[1], v3f + 3);
11332 VectorCopy(decal->vertex3f[2], v3f + 6);
11335 if (r_refdef.fogenabled)
11337 alpha = RSurf_FogVertex(v3f);
11338 VectorScale(c4f, alpha, c4f);
11339 alpha = RSurf_FogVertex(v3f + 3);
11340 VectorScale(c4f + 4, alpha, c4f + 4);
11341 alpha = RSurf_FogVertex(v3f + 6);
11342 VectorScale(c4f + 8, alpha, c4f + 8);
11353 r_refdef.stats.drawndecals += numtris;
11355 // now render the decals all at once
11356 // (this assumes they all use one particle font texture!)
11357 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);
11358 // R_Mesh_ResetTextureState();
11359 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11360 GL_DepthMask(false);
11361 GL_DepthRange(0, 1);
11362 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11363 GL_DepthTest(true);
11364 GL_CullFace(GL_NONE);
11365 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11366 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11367 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11371 static void R_DrawModelDecals(void)
11375 // fade faster when there are too many decals
11376 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11377 for (i = 0;i < r_refdef.scene.numentities;i++)
11378 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11380 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11381 for (i = 0;i < r_refdef.scene.numentities;i++)
11382 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11383 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11385 R_DecalSystem_ApplySplatEntitiesQueue();
11387 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11388 for (i = 0;i < r_refdef.scene.numentities;i++)
11389 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11391 r_refdef.stats.totaldecals += numdecals;
11393 if (r_showsurfaces.integer)
11396 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11398 for (i = 0;i < r_refdef.scene.numentities;i++)
11400 if (!r_refdef.viewcache.entityvisible[i])
11402 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11403 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11407 extern cvar_t mod_collision_bih;
11408 void R_DrawDebugModel(void)
11410 entity_render_t *ent = rsurface.entity;
11411 int i, j, k, l, flagsmask;
11412 const msurface_t *surface;
11413 dp_model_t *model = ent->model;
11416 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11419 if (r_showoverdraw.value > 0)
11421 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11422 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11423 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11424 GL_DepthTest(false);
11425 GL_DepthMask(false);
11426 GL_DepthRange(0, 1);
11427 GL_BlendFunc(GL_ONE, GL_ONE);
11428 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11430 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11432 rsurface.texture = R_GetCurrentTexture(surface->texture);
11433 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11435 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11436 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11437 if (!rsurface.texture->currentlayers->depthmask)
11438 GL_Color(c, 0, 0, 1.0f);
11439 else if (ent == r_refdef.scene.worldentity)
11440 GL_Color(c, c, c, 1.0f);
11442 GL_Color(0, c, 0, 1.0f);
11443 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11447 rsurface.texture = NULL;
11450 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11452 // R_Mesh_ResetTextureState();
11453 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11454 GL_DepthRange(0, 1);
11455 GL_DepthTest(!r_showdisabledepthtest.integer);
11456 GL_DepthMask(false);
11457 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11459 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11463 qboolean cullbox = ent == r_refdef.scene.worldentity;
11464 const q3mbrush_t *brush;
11465 const bih_t *bih = &model->collision_bih;
11466 const bih_leaf_t *bihleaf;
11467 float vertex3f[3][3];
11468 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11470 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11472 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11474 switch (bihleaf->type)
11477 brush = model->brush.data_brushes + bihleaf->itemindex;
11478 if (brush->colbrushf && brush->colbrushf->numtriangles)
11480 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);
11481 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11482 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11485 case BIH_COLLISIONTRIANGLE:
11486 triangleindex = bihleaf->itemindex;
11487 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11488 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11489 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11490 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);
11491 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11492 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11494 case BIH_RENDERTRIANGLE:
11495 triangleindex = bihleaf->itemindex;
11496 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11497 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11498 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11499 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);
11500 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11501 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11507 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11510 if (r_showtris.integer && qglPolygonMode)
11512 if (r_showdisabledepthtest.integer)
11514 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11515 GL_DepthMask(false);
11519 GL_BlendFunc(GL_ONE, GL_ZERO);
11520 GL_DepthMask(true);
11522 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11523 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11525 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11527 rsurface.texture = R_GetCurrentTexture(surface->texture);
11528 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11530 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11531 if (!rsurface.texture->currentlayers->depthmask)
11532 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11533 else if (ent == r_refdef.scene.worldentity)
11534 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11536 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11537 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11541 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11542 rsurface.texture = NULL;
11545 if (r_shownormals.value != 0 && qglBegin)
11547 if (r_showdisabledepthtest.integer)
11549 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11550 GL_DepthMask(false);
11554 GL_BlendFunc(GL_ONE, GL_ZERO);
11555 GL_DepthMask(true);
11557 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11559 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11561 rsurface.texture = R_GetCurrentTexture(surface->texture);
11562 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11564 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11565 qglBegin(GL_LINES);
11566 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11568 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11570 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11571 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11572 qglVertex3f(v[0], v[1], v[2]);
11573 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11574 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11575 qglVertex3f(v[0], v[1], v[2]);
11578 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11580 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11582 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11583 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11584 qglVertex3f(v[0], v[1], v[2]);
11585 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11586 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11587 qglVertex3f(v[0], v[1], v[2]);
11590 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11592 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11594 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11595 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11596 qglVertex3f(v[0], v[1], v[2]);
11597 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11598 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11599 qglVertex3f(v[0], v[1], v[2]);
11602 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11604 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11606 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11607 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11608 qglVertex3f(v[0], v[1], v[2]);
11609 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11610 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11611 qglVertex3f(v[0], v[1], v[2]);
11618 rsurface.texture = NULL;
11623 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11624 int r_maxsurfacelist = 0;
11625 const msurface_t **r_surfacelist = NULL;
11626 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11628 int i, j, endj, flagsmask;
11629 dp_model_t *model = r_refdef.scene.worldmodel;
11630 msurface_t *surfaces;
11631 unsigned char *update;
11632 int numsurfacelist = 0;
11636 if (r_maxsurfacelist < model->num_surfaces)
11638 r_maxsurfacelist = model->num_surfaces;
11640 Mem_Free((msurface_t**)r_surfacelist);
11641 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11644 RSurf_ActiveWorldEntity();
11646 surfaces = model->data_surfaces;
11647 update = model->brushq1.lightmapupdateflags;
11649 // update light styles on this submodel
11650 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11652 model_brush_lightstyleinfo_t *style;
11653 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11655 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11657 int *list = style->surfacelist;
11658 style->value = r_refdef.scene.lightstylevalue[style->style];
11659 for (j = 0;j < style->numsurfaces;j++)
11660 update[list[j]] = true;
11665 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11669 R_DrawDebugModel();
11670 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11674 rsurface.lightmaptexture = NULL;
11675 rsurface.deluxemaptexture = NULL;
11676 rsurface.uselightmaptexture = false;
11677 rsurface.texture = NULL;
11678 rsurface.rtlight = NULL;
11679 numsurfacelist = 0;
11680 // add visible surfaces to draw list
11681 for (i = 0;i < model->nummodelsurfaces;i++)
11683 j = model->sortedmodelsurfaces[i];
11684 if (r_refdef.viewcache.world_surfacevisible[j])
11685 r_surfacelist[numsurfacelist++] = surfaces + j;
11687 // update lightmaps if needed
11688 if (model->brushq1.firstrender)
11690 model->brushq1.firstrender = false;
11691 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11693 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11697 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11698 if (r_refdef.viewcache.world_surfacevisible[j])
11700 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11702 // don't do anything if there were no surfaces
11703 if (!numsurfacelist)
11705 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11708 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11710 // add to stats if desired
11711 if (r_speeds.integer && !skysurfaces && !depthonly)
11713 r_refdef.stats.world_surfaces += numsurfacelist;
11714 for (j = 0;j < numsurfacelist;j++)
11715 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11718 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11721 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11723 int i, j, endj, flagsmask;
11724 dp_model_t *model = ent->model;
11725 msurface_t *surfaces;
11726 unsigned char *update;
11727 int numsurfacelist = 0;
11731 if (r_maxsurfacelist < model->num_surfaces)
11733 r_maxsurfacelist = model->num_surfaces;
11735 Mem_Free((msurface_t **)r_surfacelist);
11736 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11739 // if the model is static it doesn't matter what value we give for
11740 // wantnormals and wanttangents, so this logic uses only rules applicable
11741 // to a model, knowing that they are meaningless otherwise
11742 if (ent == r_refdef.scene.worldentity)
11743 RSurf_ActiveWorldEntity();
11744 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11745 RSurf_ActiveModelEntity(ent, false, false, false);
11747 RSurf_ActiveModelEntity(ent, true, true, true);
11748 else if (depthonly)
11750 switch (vid.renderpath)
11752 case RENDERPATH_GL20:
11753 case RENDERPATH_D3D9:
11754 case RENDERPATH_D3D10:
11755 case RENDERPATH_D3D11:
11756 case RENDERPATH_SOFT:
11757 case RENDERPATH_GLES2:
11758 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11760 case RENDERPATH_GL11:
11761 case RENDERPATH_GL13:
11762 case RENDERPATH_GLES1:
11763 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11769 switch (vid.renderpath)
11771 case RENDERPATH_GL20:
11772 case RENDERPATH_D3D9:
11773 case RENDERPATH_D3D10:
11774 case RENDERPATH_D3D11:
11775 case RENDERPATH_SOFT:
11776 case RENDERPATH_GLES2:
11777 RSurf_ActiveModelEntity(ent, true, true, false);
11779 case RENDERPATH_GL11:
11780 case RENDERPATH_GL13:
11781 case RENDERPATH_GLES1:
11782 RSurf_ActiveModelEntity(ent, true, false, false);
11787 surfaces = model->data_surfaces;
11788 update = model->brushq1.lightmapupdateflags;
11790 // update light styles
11791 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11793 model_brush_lightstyleinfo_t *style;
11794 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11796 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11798 int *list = style->surfacelist;
11799 style->value = r_refdef.scene.lightstylevalue[style->style];
11800 for (j = 0;j < style->numsurfaces;j++)
11801 update[list[j]] = true;
11806 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11810 R_DrawDebugModel();
11811 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11815 rsurface.lightmaptexture = NULL;
11816 rsurface.deluxemaptexture = NULL;
11817 rsurface.uselightmaptexture = false;
11818 rsurface.texture = NULL;
11819 rsurface.rtlight = NULL;
11820 numsurfacelist = 0;
11821 // add visible surfaces to draw list
11822 for (i = 0;i < model->nummodelsurfaces;i++)
11823 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11824 // don't do anything if there were no surfaces
11825 if (!numsurfacelist)
11827 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11830 // update lightmaps if needed
11834 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11839 R_BuildLightMap(ent, surfaces + j);
11844 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11846 R_BuildLightMap(ent, surfaces + j);
11847 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11849 // add to stats if desired
11850 if (r_speeds.integer && !skysurfaces && !depthonly)
11852 r_refdef.stats.entities_surfaces += numsurfacelist;
11853 for (j = 0;j < numsurfacelist;j++)
11854 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11857 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11860 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11862 static texture_t texture;
11863 static msurface_t surface;
11864 const msurface_t *surfacelist = &surface;
11866 // fake enough texture and surface state to render this geometry
11868 texture.update_lastrenderframe = -1; // regenerate this texture
11869 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11870 texture.currentskinframe = skinframe;
11871 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11872 texture.offsetmapping = OFFSETMAPPING_OFF;
11873 texture.offsetscale = 1;
11874 texture.specularscalemod = 1;
11875 texture.specularpowermod = 1;
11877 surface.texture = &texture;
11878 surface.num_triangles = numtriangles;
11879 surface.num_firsttriangle = firsttriangle;
11880 surface.num_vertices = numvertices;
11881 surface.num_firstvertex = firstvertex;
11884 rsurface.texture = R_GetCurrentTexture(surface.texture);
11885 rsurface.lightmaptexture = NULL;
11886 rsurface.deluxemaptexture = NULL;
11887 rsurface.uselightmaptexture = false;
11888 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11891 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)
11893 static msurface_t surface;
11894 const msurface_t *surfacelist = &surface;
11896 // fake enough texture and surface state to render this geometry
11897 surface.texture = texture;
11898 surface.num_triangles = numtriangles;
11899 surface.num_firsttriangle = firsttriangle;
11900 surface.num_vertices = numvertices;
11901 surface.num_firstvertex = firstvertex;
11904 rsurface.texture = R_GetCurrentTexture(surface.texture);
11905 rsurface.lightmaptexture = NULL;
11906 rsurface.deluxemaptexture = NULL;
11907 rsurface.uselightmaptexture = false;
11908 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);