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 - NOTE: bad performance on multi-gpu!"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
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_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
84 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)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 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"};
88 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"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 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"};
91 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"};
92 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"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 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)"};
101 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)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 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."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 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."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 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"};
126 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"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 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"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
137 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148 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)"};
149 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"};
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
156 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"};
157 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"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 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"};
161 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)"};
162 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)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 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)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 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)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 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)"};
171 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)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 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"};
174 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."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
185 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)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 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"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 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"};
192 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"};
193 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221 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"};
223 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"};
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
230 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
231 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
234 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"};
236 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, requires mod_q3shader_force_terrain_alphaflag on."};
238 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)"};
240 extern cvar_t v_glslgamma;
241 extern cvar_t v_glslgamma_2d;
243 extern qboolean v_flipped_state;
245 r_framebufferstate_t r_fb;
247 /// shadow volume bsp struct with automatically growing nodes buffer
250 rtexture_t *r_texture_blanknormalmap;
251 rtexture_t *r_texture_white;
252 rtexture_t *r_texture_grey128;
253 rtexture_t *r_texture_black;
254 rtexture_t *r_texture_notexture;
255 rtexture_t *r_texture_whitecube;
256 rtexture_t *r_texture_normalizationcube;
257 rtexture_t *r_texture_fogattenuation;
258 rtexture_t *r_texture_fogheighttexture;
259 rtexture_t *r_texture_gammaramps;
260 unsigned int r_texture_gammaramps_serial;
261 //rtexture_t *r_texture_fogintensity;
262 rtexture_t *r_texture_reflectcube;
264 // TODO: hash lookups?
265 typedef struct cubemapinfo_s
272 int r_texture_numcubemaps;
273 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
275 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
276 unsigned int r_numqueries;
277 unsigned int r_maxqueries;
279 typedef struct r_qwskincache_s
281 char name[MAX_QPATH];
282 skinframe_t *skinframe;
286 static r_qwskincache_t *r_qwskincache;
287 static int r_qwskincache_size;
289 /// vertex coordinates for a quad that covers the screen exactly
290 extern const float r_screenvertex3f[12];
291 extern const float r_d3dscreenvertex3f[12];
292 const float r_screenvertex3f[12] =
299 const float r_d3dscreenvertex3f[12] =
307 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
310 for (i = 0;i < verts;i++)
321 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
324 for (i = 0;i < verts;i++)
334 // FIXME: move this to client?
337 if (gamemode == GAME_NEHAHRA)
339 Cvar_Set("gl_fogenable", "0");
340 Cvar_Set("gl_fogdensity", "0.2");
341 Cvar_Set("gl_fogred", "0.3");
342 Cvar_Set("gl_foggreen", "0.3");
343 Cvar_Set("gl_fogblue", "0.3");
345 r_refdef.fog_density = 0;
346 r_refdef.fog_red = 0;
347 r_refdef.fog_green = 0;
348 r_refdef.fog_blue = 0;
349 r_refdef.fog_alpha = 1;
350 r_refdef.fog_start = 0;
351 r_refdef.fog_end = 16384;
352 r_refdef.fog_height = 1<<30;
353 r_refdef.fog_fadedepth = 128;
354 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
357 static void R_BuildBlankTextures(void)
359 unsigned char data[4];
360 data[2] = 128; // normal X
361 data[1] = 128; // normal Y
362 data[0] = 255; // normal Z
363 data[3] = 255; // height
364 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382 static void R_BuildNoTexture(void)
385 unsigned char pix[16][16][4];
386 // this makes a light grey/dark grey checkerboard texture
387 for (y = 0;y < 16;y++)
389 for (x = 0;x < 16;x++)
391 if ((y < 8) ^ (x < 8))
407 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
410 static void R_BuildWhiteCube(void)
412 unsigned char data[6*1*1*4];
413 memset(data, 255, sizeof(data));
414 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
417 static void R_BuildNormalizationCube(void)
421 vec_t s, t, intensity;
424 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
425 for (side = 0;side < 6;side++)
427 for (y = 0;y < NORMSIZE;y++)
429 for (x = 0;x < NORMSIZE;x++)
431 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
467 intensity = 127.0f / sqrt(DotProduct(v, v));
468 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
469 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
470 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
471 data[((side*64+y)*64+x)*4+3] = 255;
475 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
479 static void R_BuildFogTexture(void)
483 unsigned char data1[FOGWIDTH][4];
484 //unsigned char data2[FOGWIDTH][4];
487 r_refdef.fogmasktable_start = r_refdef.fog_start;
488 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
489 r_refdef.fogmasktable_range = r_refdef.fogrange;
490 r_refdef.fogmasktable_density = r_refdef.fog_density;
492 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
493 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
495 d = (x * r - r_refdef.fogmasktable_start);
496 if(developer_extra.integer)
497 Con_DPrintf("%f ", d);
499 if (r_fog_exp2.integer)
500 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
502 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
503 if(developer_extra.integer)
504 Con_DPrintf(" : %f ", alpha);
505 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
506 if(developer_extra.integer)
507 Con_DPrintf(" = %f\n", alpha);
508 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
511 for (x = 0;x < FOGWIDTH;x++)
513 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
518 //data2[x][0] = 255 - b;
519 //data2[x][1] = 255 - b;
520 //data2[x][2] = 255 - b;
523 if (r_texture_fogattenuation)
525 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
530 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
531 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
535 static void R_BuildFogHeightTexture(void)
537 unsigned char *inpixels;
545 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
546 if (r_refdef.fogheighttexturename[0])
547 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
550 r_refdef.fog_height_tablesize = 0;
551 if (r_texture_fogheighttexture)
552 R_FreeTexture(r_texture_fogheighttexture);
553 r_texture_fogheighttexture = NULL;
554 if (r_refdef.fog_height_table2d)
555 Mem_Free(r_refdef.fog_height_table2d);
556 r_refdef.fog_height_table2d = NULL;
557 if (r_refdef.fog_height_table1d)
558 Mem_Free(r_refdef.fog_height_table1d);
559 r_refdef.fog_height_table1d = NULL;
563 r_refdef.fog_height_tablesize = size;
564 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
565 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
566 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
568 // LordHavoc: now the magic - what is that table2d for? it is a cooked
569 // average fog color table accounting for every fog layer between a point
570 // and the camera. (Note: attenuation is handled separately!)
571 for (y = 0;y < size;y++)
573 for (x = 0;x < size;x++)
579 for (j = x;j <= y;j++)
581 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587 for (j = x;j >= y;j--)
589 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
595 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
596 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
597 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
600 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
603 //=======================================================================================================================================================
605 static const char *builtinshaderstring =
606 #include "shader_glsl.h"
609 const char *builtinhlslshaderstring =
610 #include "shader_hlsl.h"
613 char *glslshaderstring = NULL;
614 char *hlslshaderstring = NULL;
616 //=======================================================================================================================================================
618 typedef struct shaderpermutationinfo_s
623 shaderpermutationinfo_t;
625 typedef struct shadermodeinfo_s
627 const char *vertexfilename;
628 const char *geometryfilename;
629 const char *fragmentfilename;
635 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
636 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
638 {"#define USEDIFFUSE\n", " diffuse"},
639 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
640 {"#define USEVIEWTINT\n", " viewtint"},
641 {"#define USECOLORMAPPING\n", " colormapping"},
642 {"#define USESATURATION\n", " saturation"},
643 {"#define USEFOGINSIDE\n", " foginside"},
644 {"#define USEFOGOUTSIDE\n", " fogoutside"},
645 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
646 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
647 {"#define USEGAMMARAMPS\n", " gammaramps"},
648 {"#define USECUBEFILTER\n", " cubefilter"},
649 {"#define USEGLOW\n", " glow"},
650 {"#define USEBLOOM\n", " bloom"},
651 {"#define USESPECULAR\n", " specular"},
652 {"#define USEPOSTPROCESSING\n", " postprocessing"},
653 {"#define USEREFLECTION\n", " reflection"},
654 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
655 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
656 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
657 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
658 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
659 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
660 {"#define USEALPHAKILL\n", " alphakill"},
661 {"#define USEREFLECTCUBE\n", " reflectcube"},
662 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
663 {"#define USEBOUNCEGRID\n", " bouncegrid"},
664 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
665 {"#define USETRIPPY\n", " trippy"},
666 {"#define USEDEPTHRGB\n", " depthrgb"},
667 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
668 {"#define USESKELETAL\n", " skeletal"}
671 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
672 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
681 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
682 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
683 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
684 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
685 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
686 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
687 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
690 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
694 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
701 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
702 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
703 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
706 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
707 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 struct r_glsl_permutation_s;
717 typedef struct r_glsl_permutation_s
720 struct r_glsl_permutation_s *hashnext;
722 unsigned int permutation;
724 /// indicates if we have tried compiling this permutation already
726 /// 0 if compilation failed
728 // texture units assigned to each detected uniform
729 int tex_Texture_First;
730 int tex_Texture_Second;
731 int tex_Texture_GammaRamps;
732 int tex_Texture_Normal;
733 int tex_Texture_Color;
734 int tex_Texture_Gloss;
735 int tex_Texture_Glow;
736 int tex_Texture_SecondaryNormal;
737 int tex_Texture_SecondaryColor;
738 int tex_Texture_SecondaryGloss;
739 int tex_Texture_SecondaryGlow;
740 int tex_Texture_Pants;
741 int tex_Texture_Shirt;
742 int tex_Texture_FogHeightTexture;
743 int tex_Texture_FogMask;
744 int tex_Texture_Lightmap;
745 int tex_Texture_Deluxemap;
746 int tex_Texture_Attenuation;
747 int tex_Texture_Cube;
748 int tex_Texture_Refraction;
749 int tex_Texture_Reflection;
750 int tex_Texture_ShadowMap2D;
751 int tex_Texture_CubeProjection;
752 int tex_Texture_ScreenNormalMap;
753 int tex_Texture_ScreenDiffuse;
754 int tex_Texture_ScreenSpecular;
755 int tex_Texture_ReflectMask;
756 int tex_Texture_ReflectCube;
757 int tex_Texture_BounceGrid;
758 /// locations of detected uniforms in program object, or -1 if not found
759 int loc_Texture_First;
760 int loc_Texture_Second;
761 int loc_Texture_GammaRamps;
762 int loc_Texture_Normal;
763 int loc_Texture_Color;
764 int loc_Texture_Gloss;
765 int loc_Texture_Glow;
766 int loc_Texture_SecondaryNormal;
767 int loc_Texture_SecondaryColor;
768 int loc_Texture_SecondaryGloss;
769 int loc_Texture_SecondaryGlow;
770 int loc_Texture_Pants;
771 int loc_Texture_Shirt;
772 int loc_Texture_FogHeightTexture;
773 int loc_Texture_FogMask;
774 int loc_Texture_Lightmap;
775 int loc_Texture_Deluxemap;
776 int loc_Texture_Attenuation;
777 int loc_Texture_Cube;
778 int loc_Texture_Refraction;
779 int loc_Texture_Reflection;
780 int loc_Texture_ShadowMap2D;
781 int loc_Texture_CubeProjection;
782 int loc_Texture_ScreenNormalMap;
783 int loc_Texture_ScreenDiffuse;
784 int loc_Texture_ScreenSpecular;
785 int loc_Texture_ReflectMask;
786 int loc_Texture_ReflectCube;
787 int loc_Texture_BounceGrid;
789 int loc_BloomBlur_Parameters;
791 int loc_Color_Ambient;
792 int loc_Color_Diffuse;
793 int loc_Color_Specular;
797 int loc_DeferredColor_Ambient;
798 int loc_DeferredColor_Diffuse;
799 int loc_DeferredColor_Specular;
800 int loc_DeferredMod_Diffuse;
801 int loc_DeferredMod_Specular;
802 int loc_DistortScaleRefractReflect;
805 int loc_FogHeightFade;
807 int loc_FogPlaneViewDist;
808 int loc_FogRangeRecip;
811 int loc_LightPosition;
812 int loc_OffsetMapping_ScaleSteps;
813 int loc_OffsetMapping_LodDistance;
814 int loc_OffsetMapping_Bias;
816 int loc_ReflectColor;
817 int loc_ReflectFactor;
818 int loc_ReflectOffset;
819 int loc_RefractColor;
821 int loc_ScreenCenterRefractReflect;
822 int loc_ScreenScaleRefractReflect;
823 int loc_ScreenToDepth;
824 int loc_ShadowMap_Parameters;
825 int loc_ShadowMap_TextureScale;
826 int loc_SpecularPower;
827 int loc_Skeletal_Transform12;
832 int loc_ViewTintColor;
834 int loc_ModelToLight;
836 int loc_BackgroundTexMatrix;
837 int loc_ModelViewProjectionMatrix;
838 int loc_ModelViewMatrix;
839 int loc_PixelToScreenTexCoord;
840 int loc_ModelToReflectCube;
841 int loc_ShadowMapMatrix;
842 int loc_BloomColorSubtract;
843 int loc_NormalmapScrollBlend;
844 int loc_BounceGridMatrix;
845 int loc_BounceGridIntensity;
847 r_glsl_permutation_t;
849 #define SHADERPERMUTATION_HASHSIZE 256
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
856 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
862 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
863 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
864 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
865 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
866 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
867 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
868 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
870 #define SHADERSTATICPARMS_COUNT 13
872 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
873 static int shaderstaticparms_count = 0;
875 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
876 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
878 extern qboolean r_shadow_shadowmapsampler;
879 extern int r_shadow_shadowmappcf;
880 qboolean R_CompileShader_CheckStaticParms(void)
882 static int r_compileshader_staticparms_save[1];
883 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
887 if (r_glsl_saturation_redcompensate.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889 if (r_glsl_vertextextureblend_usebothalphas.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891 if (r_shadow_glossexact.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893 if (r_glsl_postprocess.integer)
895 if (r_glsl_postprocess_uservec1_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897 if (r_glsl_postprocess_uservec2_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899 if (r_glsl_postprocess_uservec3_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901 if (r_glsl_postprocess_uservec4_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
904 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
905 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
907 if (r_shadow_shadowmapsampler)
908 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
909 if (r_shadow_shadowmappcf > 1)
910 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
911 else if (r_shadow_shadowmappcf)
912 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
913 if (r_celshading.integer)
914 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
915 if (r_celoutlines.integer)
916 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
918 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
921 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
922 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
923 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
925 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
926 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
928 shaderstaticparms_count = 0;
931 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
932 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
933 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
934 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
935 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
936 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
937 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
938 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
939 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
940 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
941 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
942 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
943 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
946 /// information about each possible shader permutation
947 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
948 /// currently selected permutation
949 r_glsl_permutation_t *r_glsl_permutation;
950 /// storage for permutations linked in the hash table
951 memexpandablearray_t r_glsl_permutationarray;
953 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
955 //unsigned int hashdepth = 0;
956 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
957 r_glsl_permutation_t *p;
958 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
960 if (p->mode == mode && p->permutation == permutation)
962 //if (hashdepth > 10)
963 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
970 p->permutation = permutation;
971 p->hashnext = r_glsl_permutationhash[mode][hashindex];
972 r_glsl_permutationhash[mode][hashindex] = p;
973 //if (hashdepth > 10)
974 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
978 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
981 if (!filename || !filename[0])
983 if (!strcmp(filename, "glsl/default.glsl"))
985 if (!glslshaderstring)
987 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988 if (glslshaderstring)
989 Con_DPrintf("Loading shaders from file %s...\n", filename);
991 glslshaderstring = (char *)builtinshaderstring;
993 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
994 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
997 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1000 if (printfromdisknotice)
1001 Con_DPrintf("from disk %s... ", filename);
1002 return shaderstring;
1004 return shaderstring;
1007 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1011 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1012 char *vertexstring, *geometrystring, *fragmentstring;
1013 char permutationname[256];
1014 int vertstrings_count = 0;
1015 int geomstrings_count = 0;
1016 int fragstrings_count = 0;
1017 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1018 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1019 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1026 permutationname[0] = 0;
1027 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1028 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1029 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1031 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1033 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1034 if(vid.support.gl20shaders130)
1036 vertstrings_list[vertstrings_count++] = "#version 130\n";
1037 geomstrings_list[geomstrings_count++] = "#version 130\n";
1038 fragstrings_list[fragstrings_count++] = "#version 130\n";
1039 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1040 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1041 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1044 // the first pretext is which type of shader to compile as
1045 // (later these will all be bound together as a program object)
1046 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1047 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1048 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1050 // the second pretext is the mode (for example a light source)
1051 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1052 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1053 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1054 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1056 // now add all the permutation pretexts
1057 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1059 if (permutation & (1<<i))
1061 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1062 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1063 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1064 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1068 // keep line numbers correct
1069 vertstrings_list[vertstrings_count++] = "\n";
1070 geomstrings_list[geomstrings_count++] = "\n";
1071 fragstrings_list[fragstrings_count++] = "\n";
1076 R_CompileShader_AddStaticParms(mode, permutation);
1077 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1078 vertstrings_count += shaderstaticparms_count;
1079 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1080 geomstrings_count += shaderstaticparms_count;
1081 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1082 fragstrings_count += shaderstaticparms_count;
1084 // now append the shader text itself
1085 vertstrings_list[vertstrings_count++] = vertexstring;
1086 geomstrings_list[geomstrings_count++] = geometrystring;
1087 fragstrings_list[fragstrings_count++] = fragmentstring;
1089 // if any sources were NULL, clear the respective list
1091 vertstrings_count = 0;
1092 if (!geometrystring)
1093 geomstrings_count = 0;
1094 if (!fragmentstring)
1095 fragstrings_count = 0;
1097 // compile the shader program
1098 if (vertstrings_count + geomstrings_count + fragstrings_count)
1099 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1103 qglUseProgram(p->program);CHECKGLERROR
1104 // look up all the uniform variable names we care about, so we don't
1105 // have to look them up every time we set them
1107 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1108 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1109 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1110 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1111 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1112 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1113 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1114 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1115 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1116 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1117 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1118 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1119 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1120 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1121 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1122 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1123 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1124 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1125 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1126 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1127 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1128 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1129 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1130 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1131 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1132 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1133 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1134 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1135 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1136 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1137 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1138 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1139 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1140 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1141 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1142 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1143 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1144 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1145 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1146 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1147 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1148 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1149 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1150 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1151 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1152 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1153 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1154 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1155 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1156 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1157 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1158 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1159 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1160 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1161 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1162 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1163 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1164 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1165 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1166 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1167 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1168 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1169 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1170 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1171 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1172 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1173 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1174 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1175 p->loc_Skeletal_Transform12 = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1176 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1177 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1178 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1179 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1180 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1181 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1182 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1183 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1184 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1185 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1186 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1187 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1188 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1189 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1190 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1191 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1192 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1193 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1194 // initialize the samplers to refer to the texture units we use
1195 p->tex_Texture_First = -1;
1196 p->tex_Texture_Second = -1;
1197 p->tex_Texture_GammaRamps = -1;
1198 p->tex_Texture_Normal = -1;
1199 p->tex_Texture_Color = -1;
1200 p->tex_Texture_Gloss = -1;
1201 p->tex_Texture_Glow = -1;
1202 p->tex_Texture_SecondaryNormal = -1;
1203 p->tex_Texture_SecondaryColor = -1;
1204 p->tex_Texture_SecondaryGloss = -1;
1205 p->tex_Texture_SecondaryGlow = -1;
1206 p->tex_Texture_Pants = -1;
1207 p->tex_Texture_Shirt = -1;
1208 p->tex_Texture_FogHeightTexture = -1;
1209 p->tex_Texture_FogMask = -1;
1210 p->tex_Texture_Lightmap = -1;
1211 p->tex_Texture_Deluxemap = -1;
1212 p->tex_Texture_Attenuation = -1;
1213 p->tex_Texture_Cube = -1;
1214 p->tex_Texture_Refraction = -1;
1215 p->tex_Texture_Reflection = -1;
1216 p->tex_Texture_ShadowMap2D = -1;
1217 p->tex_Texture_CubeProjection = -1;
1218 p->tex_Texture_ScreenNormalMap = -1;
1219 p->tex_Texture_ScreenDiffuse = -1;
1220 p->tex_Texture_ScreenSpecular = -1;
1221 p->tex_Texture_ReflectMask = -1;
1222 p->tex_Texture_ReflectCube = -1;
1223 p->tex_Texture_BounceGrid = -1;
1225 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1226 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1227 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1228 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1229 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1230 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1231 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1232 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1233 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1234 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1235 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1236 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1237 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1238 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1239 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1240 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1241 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1242 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1243 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1244 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1245 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1246 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1247 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1248 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1249 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1250 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1251 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1252 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1253 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1255 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1258 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1262 Mem_Free(vertexstring);
1264 Mem_Free(geometrystring);
1266 Mem_Free(fragmentstring);
1269 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1271 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1272 if (r_glsl_permutation != perm)
1274 r_glsl_permutation = perm;
1275 if (!r_glsl_permutation->program)
1277 if (!r_glsl_permutation->compiled)
1278 R_GLSL_CompilePermutation(perm, mode, permutation);
1279 if (!r_glsl_permutation->program)
1281 // remove features until we find a valid permutation
1283 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1285 // reduce i more quickly whenever it would not remove any bits
1286 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1287 if (!(permutation & j))
1290 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291 if (!r_glsl_permutation->compiled)
1292 R_GLSL_CompilePermutation(perm, mode, permutation);
1293 if (r_glsl_permutation->program)
1296 if (i >= SHADERPERMUTATION_COUNT)
1298 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1299 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1300 qglUseProgram(0);CHECKGLERROR
1301 return; // no bit left to clear, entire mode is broken
1306 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1308 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1309 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1310 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1317 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1318 extern D3DCAPS9 vid_d3d9caps;
1321 struct r_hlsl_permutation_s;
1322 typedef struct r_hlsl_permutation_s
1324 /// hash lookup data
1325 struct r_hlsl_permutation_s *hashnext;
1327 unsigned int permutation;
1329 /// indicates if we have tried compiling this permutation already
1331 /// NULL if compilation failed
1332 IDirect3DVertexShader9 *vertexshader;
1333 IDirect3DPixelShader9 *pixelshader;
1335 r_hlsl_permutation_t;
1337 typedef enum D3DVSREGISTER_e
1339 D3DVSREGISTER_TexMatrix = 0, // float4x4
1340 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1341 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1342 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1343 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1344 D3DVSREGISTER_ModelToLight = 20, // float4x4
1345 D3DVSREGISTER_EyePosition = 24,
1346 D3DVSREGISTER_FogPlane = 25,
1347 D3DVSREGISTER_LightDir = 26,
1348 D3DVSREGISTER_LightPosition = 27,
1352 typedef enum D3DPSREGISTER_e
1354 D3DPSREGISTER_Alpha = 0,
1355 D3DPSREGISTER_BloomBlur_Parameters = 1,
1356 D3DPSREGISTER_ClientTime = 2,
1357 D3DPSREGISTER_Color_Ambient = 3,
1358 D3DPSREGISTER_Color_Diffuse = 4,
1359 D3DPSREGISTER_Color_Specular = 5,
1360 D3DPSREGISTER_Color_Glow = 6,
1361 D3DPSREGISTER_Color_Pants = 7,
1362 D3DPSREGISTER_Color_Shirt = 8,
1363 D3DPSREGISTER_DeferredColor_Ambient = 9,
1364 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1365 D3DPSREGISTER_DeferredColor_Specular = 11,
1366 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1367 D3DPSREGISTER_DeferredMod_Specular = 13,
1368 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1369 D3DPSREGISTER_EyePosition = 15, // unused
1370 D3DPSREGISTER_FogColor = 16,
1371 D3DPSREGISTER_FogHeightFade = 17,
1372 D3DPSREGISTER_FogPlane = 18,
1373 D3DPSREGISTER_FogPlaneViewDist = 19,
1374 D3DPSREGISTER_FogRangeRecip = 20,
1375 D3DPSREGISTER_LightColor = 21,
1376 D3DPSREGISTER_LightDir = 22, // unused
1377 D3DPSREGISTER_LightPosition = 23,
1378 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1379 D3DPSREGISTER_PixelSize = 25,
1380 D3DPSREGISTER_ReflectColor = 26,
1381 D3DPSREGISTER_ReflectFactor = 27,
1382 D3DPSREGISTER_ReflectOffset = 28,
1383 D3DPSREGISTER_RefractColor = 29,
1384 D3DPSREGISTER_Saturation = 30,
1385 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1386 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1387 D3DPSREGISTER_ScreenToDepth = 33,
1388 D3DPSREGISTER_ShadowMap_Parameters = 34,
1389 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1390 D3DPSREGISTER_SpecularPower = 36,
1391 D3DPSREGISTER_UserVec1 = 37,
1392 D3DPSREGISTER_UserVec2 = 38,
1393 D3DPSREGISTER_UserVec3 = 39,
1394 D3DPSREGISTER_UserVec4 = 40,
1395 D3DPSREGISTER_ViewTintColor = 41,
1396 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1397 D3DPSREGISTER_BloomColorSubtract = 43,
1398 D3DPSREGISTER_ViewToLight = 44, // float4x4
1399 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1400 D3DPSREGISTER_NormalmapScrollBlend = 52,
1401 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1402 D3DPSREGISTER_OffsetMapping_Bias = 54,
1407 /// information about each possible shader permutation
1408 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1409 /// currently selected permutation
1410 r_hlsl_permutation_t *r_hlsl_permutation;
1411 /// storage for permutations linked in the hash table
1412 memexpandablearray_t r_hlsl_permutationarray;
1414 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1416 //unsigned int hashdepth = 0;
1417 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1418 r_hlsl_permutation_t *p;
1419 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1421 if (p->mode == mode && p->permutation == permutation)
1423 //if (hashdepth > 10)
1424 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1429 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1431 p->permutation = permutation;
1432 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1433 r_hlsl_permutationhash[mode][hashindex] = p;
1434 //if (hashdepth > 10)
1435 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1439 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1442 if (!filename || !filename[0])
1444 if (!strcmp(filename, "hlsl/default.hlsl"))
1446 if (!hlslshaderstring)
1448 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449 if (hlslshaderstring)
1450 Con_DPrintf("Loading shaders from file %s...\n", filename);
1452 hlslshaderstring = (char *)builtinhlslshaderstring;
1454 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1455 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1456 return shaderstring;
1458 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1461 if (printfromdisknotice)
1462 Con_DPrintf("from disk %s... ", filename);
1463 return shaderstring;
1465 return shaderstring;
1469 //#include <d3dx9shader.h>
1470 //#include <d3dx9mesh.h>
1472 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1474 DWORD *vsbin = NULL;
1475 DWORD *psbin = NULL;
1476 fs_offset_t vsbinsize;
1477 fs_offset_t psbinsize;
1478 // IDirect3DVertexShader9 *vs = NULL;
1479 // IDirect3DPixelShader9 *ps = NULL;
1480 ID3DXBuffer *vslog = NULL;
1481 ID3DXBuffer *vsbuffer = NULL;
1482 ID3DXConstantTable *vsconstanttable = NULL;
1483 ID3DXBuffer *pslog = NULL;
1484 ID3DXBuffer *psbuffer = NULL;
1485 ID3DXConstantTable *psconstanttable = NULL;
1488 char temp[MAX_INPUTLINE];
1489 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1491 qboolean debugshader = gl_paranoid.integer != 0;
1492 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1496 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1497 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1499 if ((!vsbin && vertstring) || (!psbin && fragstring))
1501 const char* dllnames_d3dx9 [] =
1525 dllhandle_t d3dx9_dll = NULL;
1526 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1527 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1528 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1529 dllfunction_t d3dx9_dllfuncs[] =
1531 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1532 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1533 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1536 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1538 DWORD shaderflags = 0;
1540 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1541 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1542 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1543 if (vertstring && vertstring[0])
1547 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1548 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1551 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1554 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1555 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1556 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1557 ID3DXBuffer_Release(vsbuffer);
1561 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1562 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1563 ID3DXBuffer_Release(vslog);
1566 if (fragstring && fragstring[0])
1570 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1571 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1574 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1577 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1578 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1579 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1580 ID3DXBuffer_Release(psbuffer);
1584 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1585 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1586 ID3DXBuffer_Release(pslog);
1589 Sys_UnloadLibrary(&d3dx9_dll);
1592 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1596 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1597 if (FAILED(vsresult))
1598 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1599 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1600 if (FAILED(psresult))
1601 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1603 // free the shader data
1604 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1605 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1608 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1611 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1612 int vertstring_length = 0;
1613 int geomstring_length = 0;
1614 int fragstring_length = 0;
1616 char *vertexstring, *geometrystring, *fragmentstring;
1617 char *vertstring, *geomstring, *fragstring;
1618 char permutationname[256];
1619 char cachename[256];
1620 int vertstrings_count = 0;
1621 int geomstrings_count = 0;
1622 int fragstrings_count = 0;
1623 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1624 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1625 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1630 p->vertexshader = NULL;
1631 p->pixelshader = NULL;
1633 permutationname[0] = 0;
1635 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1636 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1637 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1639 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1640 strlcat(cachename, "hlsl/", sizeof(cachename));
1642 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1643 vertstrings_count = 0;
1644 geomstrings_count = 0;
1645 fragstrings_count = 0;
1646 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1647 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1648 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1650 // the first pretext is which type of shader to compile as
1651 // (later these will all be bound together as a program object)
1652 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1653 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1654 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1656 // the second pretext is the mode (for example a light source)
1657 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1658 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1659 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1660 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1661 strlcat(cachename, modeinfo->name, sizeof(cachename));
1663 // now add all the permutation pretexts
1664 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1666 if (permutation & (1<<i))
1668 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1669 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1670 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1671 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1672 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1676 // keep line numbers correct
1677 vertstrings_list[vertstrings_count++] = "\n";
1678 geomstrings_list[geomstrings_count++] = "\n";
1679 fragstrings_list[fragstrings_count++] = "\n";
1684 R_CompileShader_AddStaticParms(mode, permutation);
1685 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686 vertstrings_count += shaderstaticparms_count;
1687 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688 geomstrings_count += shaderstaticparms_count;
1689 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1690 fragstrings_count += shaderstaticparms_count;
1692 // replace spaces in the cachename with _ characters
1693 for (i = 0;cachename[i];i++)
1694 if (cachename[i] == ' ')
1697 // now append the shader text itself
1698 vertstrings_list[vertstrings_count++] = vertexstring;
1699 geomstrings_list[geomstrings_count++] = geometrystring;
1700 fragstrings_list[fragstrings_count++] = fragmentstring;
1702 // if any sources were NULL, clear the respective list
1704 vertstrings_count = 0;
1705 if (!geometrystring)
1706 geomstrings_count = 0;
1707 if (!fragmentstring)
1708 fragstrings_count = 0;
1710 vertstring_length = 0;
1711 for (i = 0;i < vertstrings_count;i++)
1712 vertstring_length += strlen(vertstrings_list[i]);
1713 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1714 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1715 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1717 geomstring_length = 0;
1718 for (i = 0;i < geomstrings_count;i++)
1719 geomstring_length += strlen(geomstrings_list[i]);
1720 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1721 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1722 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1724 fragstring_length = 0;
1725 for (i = 0;i < fragstrings_count;i++)
1726 fragstring_length += strlen(fragstrings_list[i]);
1727 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1728 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1729 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1731 // try to load the cached shader, or generate one
1732 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1734 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1735 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1737 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1741 Mem_Free(vertstring);
1743 Mem_Free(geomstring);
1745 Mem_Free(fragstring);
1747 Mem_Free(vertexstring);
1749 Mem_Free(geometrystring);
1751 Mem_Free(fragmentstring);
1754 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 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);}
1757 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);}
1758 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);}
1759 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);}
1761 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1762 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1763 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);}
1764 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);}
1765 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);}
1766 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);}
1768 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1770 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1771 if (r_hlsl_permutation != perm)
1773 r_hlsl_permutation = perm;
1774 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1776 if (!r_hlsl_permutation->compiled)
1777 R_HLSL_CompilePermutation(perm, mode, permutation);
1778 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1780 // remove features until we find a valid permutation
1782 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1784 // reduce i more quickly whenever it would not remove any bits
1785 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1786 if (!(permutation & j))
1789 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1790 if (!r_hlsl_permutation->compiled)
1791 R_HLSL_CompilePermutation(perm, mode, permutation);
1792 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1795 if (i >= SHADERPERMUTATION_COUNT)
1797 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1798 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1799 return; // no bit left to clear, entire mode is broken
1803 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1804 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1806 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1807 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1808 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1812 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1814 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1815 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1816 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1817 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1820 void R_GLSL_Restart_f(void)
1822 unsigned int i, limit;
1823 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1824 Mem_Free(glslshaderstring);
1825 glslshaderstring = NULL;
1826 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1827 Mem_Free(hlslshaderstring);
1828 hlslshaderstring = NULL;
1829 switch(vid.renderpath)
1831 case RENDERPATH_D3D9:
1834 r_hlsl_permutation_t *p;
1835 r_hlsl_permutation = NULL;
1836 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1837 for (i = 0;i < limit;i++)
1839 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1841 if (p->vertexshader)
1842 IDirect3DVertexShader9_Release(p->vertexshader);
1844 IDirect3DPixelShader9_Release(p->pixelshader);
1845 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1848 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1852 case RENDERPATH_D3D10:
1853 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1855 case RENDERPATH_D3D11:
1856 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1858 case RENDERPATH_GL20:
1859 case RENDERPATH_GLES2:
1861 r_glsl_permutation_t *p;
1862 r_glsl_permutation = NULL;
1863 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1864 for (i = 0;i < limit;i++)
1866 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1868 GL_Backend_FreeProgram(p->program);
1869 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1872 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1875 case RENDERPATH_GL11:
1876 case RENDERPATH_GL13:
1877 case RENDERPATH_GLES1:
1879 case RENDERPATH_SOFT:
1884 static void R_GLSL_DumpShader_f(void)
1889 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1892 FS_Print(file, "/* The engine may define the following macros:\n");
1893 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894 for (i = 0;i < SHADERMODE_COUNT;i++)
1895 FS_Print(file, glslshadermodeinfo[i].pretext);
1896 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897 FS_Print(file, shaderpermutationinfo[i].pretext);
1898 FS_Print(file, "*/\n");
1899 FS_Print(file, builtinshaderstring);
1901 Con_Printf("glsl/default.glsl written\n");
1904 Con_Printf("failed to write to glsl/default.glsl\n");
1906 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1909 FS_Print(file, "/* The engine may define the following macros:\n");
1910 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1911 for (i = 0;i < SHADERMODE_COUNT;i++)
1912 FS_Print(file, hlslshadermodeinfo[i].pretext);
1913 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1914 FS_Print(file, shaderpermutationinfo[i].pretext);
1915 FS_Print(file, "*/\n");
1916 FS_Print(file, builtinhlslshaderstring);
1918 Con_Printf("hlsl/default.hlsl written\n");
1921 Con_Printf("failed to write to hlsl/default.hlsl\n");
1924 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1926 unsigned int permutation = 0;
1927 if (r_trippy.integer && !notrippy)
1928 permutation |= SHADERPERMUTATION_TRIPPY;
1929 permutation |= SHADERPERMUTATION_VIEWTINT;
1931 permutation |= SHADERPERMUTATION_DIFFUSE;
1933 permutation |= SHADERPERMUTATION_SPECULAR;
1934 if (texturemode == GL_MODULATE)
1935 permutation |= SHADERPERMUTATION_COLORMAPPING;
1936 else if (texturemode == GL_ADD)
1937 permutation |= SHADERPERMUTATION_GLOW;
1938 else if (texturemode == GL_DECAL)
1939 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1940 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1941 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1942 if (suppresstexalpha)
1943 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1945 texturemode = GL_MODULATE;
1946 if (vid.allowalphatocoverage)
1947 GL_AlphaToCoverage(false);
1948 switch (vid.renderpath)
1950 case RENDERPATH_D3D9:
1952 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1953 R_Mesh_TexBind(GL20TU_FIRST , first );
1954 R_Mesh_TexBind(GL20TU_SECOND, second);
1955 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1956 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1959 case RENDERPATH_D3D10:
1960 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962 case RENDERPATH_D3D11:
1963 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965 case RENDERPATH_GL20:
1966 case RENDERPATH_GLES2:
1967 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1968 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1969 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1970 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1971 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1973 case RENDERPATH_GL13:
1974 case RENDERPATH_GLES1:
1975 R_Mesh_TexBind(0, first );
1976 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1977 R_Mesh_TexBind(1, second);
1979 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1981 case RENDERPATH_GL11:
1982 R_Mesh_TexBind(0, first );
1984 case RENDERPATH_SOFT:
1985 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1986 R_Mesh_TexBind(GL20TU_FIRST , first );
1987 R_Mesh_TexBind(GL20TU_SECOND, second);
1992 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1994 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1997 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1999 unsigned int permutation = 0;
2000 if (r_trippy.integer && !notrippy)
2001 permutation |= SHADERPERMUTATION_TRIPPY;
2003 permutation |= SHADERPERMUTATION_DEPTHRGB;
2004 if (vid.allowalphatocoverage)
2005 GL_AlphaToCoverage(false);
2006 switch (vid.renderpath)
2008 case RENDERPATH_D3D9:
2010 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2013 case RENDERPATH_D3D10:
2014 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016 case RENDERPATH_D3D11:
2017 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2019 case RENDERPATH_GL20:
2020 case RENDERPATH_GLES2:
2021 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2023 case RENDERPATH_GL13:
2024 case RENDERPATH_GLES1:
2025 R_Mesh_TexBind(0, 0);
2026 R_Mesh_TexBind(1, 0);
2028 case RENDERPATH_GL11:
2029 R_Mesh_TexBind(0, 0);
2031 case RENDERPATH_SOFT:
2032 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2037 void R_SetupShader_ShowDepth(qboolean notrippy)
2039 int permutation = 0;
2040 if (r_trippy.integer && !notrippy)
2041 permutation |= SHADERPERMUTATION_TRIPPY;
2042 if (vid.allowalphatocoverage)
2043 GL_AlphaToCoverage(false);
2044 switch (vid.renderpath)
2046 case RENDERPATH_D3D9:
2048 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2051 case RENDERPATH_D3D10:
2052 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2054 case RENDERPATH_D3D11:
2055 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057 case RENDERPATH_GL20:
2058 case RENDERPATH_GLES2:
2059 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2061 case RENDERPATH_GL13:
2062 case RENDERPATH_GLES1:
2064 case RENDERPATH_GL11:
2066 case RENDERPATH_SOFT:
2067 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2072 extern qboolean r_shadow_usingdeferredprepass;
2073 extern rtexture_t *r_shadow_attenuationgradienttexture;
2074 extern rtexture_t *r_shadow_attenuation2dtexture;
2075 extern rtexture_t *r_shadow_attenuation3dtexture;
2076 extern qboolean r_shadow_usingshadowmap2d;
2077 extern qboolean r_shadow_usingshadowmaportho;
2078 extern float r_shadow_shadowmap_texturescale[2];
2079 extern float r_shadow_shadowmap_parameters[4];
2080 extern qboolean r_shadow_shadowmapvsdct;
2081 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2082 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2083 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2084 extern matrix4x4_t r_shadow_shadowmapmatrix;
2085 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2086 extern int r_shadow_prepass_width;
2087 extern int r_shadow_prepass_height;
2088 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2089 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2090 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2091 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2093 #define BLENDFUNC_ALLOWS_COLORMOD 1
2094 #define BLENDFUNC_ALLOWS_FOG 2
2095 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2096 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2097 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2098 static int R_BlendFuncFlags(int src, int dst)
2102 // a blendfunc allows colormod if:
2103 // a) it can never keep the destination pixel invariant, or
2104 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2105 // this is to prevent unintended side effects from colormod
2107 // a blendfunc allows fog if:
2108 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2109 // this is to prevent unintended side effects from fog
2111 // these checks are the output of fogeval.pl
2113 r |= BLENDFUNC_ALLOWS_COLORMOD;
2114 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2118 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2121 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2123 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2124 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2125 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2127 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2128 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2129 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2131 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2132 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2133 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2134 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2139 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)
2141 // select a permutation of the lighting shader appropriate to this
2142 // combination of texture, entity, light source, and fogging, only use the
2143 // minimum features necessary to avoid wasting rendering time in the
2144 // fragment shader on features that are not being used
2145 unsigned int permutation = 0;
2146 unsigned int mode = 0;
2148 static float dummy_colormod[3] = {1, 1, 1};
2149 float *colormod = rsurface.colormod;
2151 matrix4x4_t tempmatrix;
2152 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2153 if (r_trippy.integer && !notrippy)
2154 permutation |= SHADERPERMUTATION_TRIPPY;
2155 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2156 permutation |= SHADERPERMUTATION_ALPHAKILL;
2157 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2158 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2159 if (rsurfacepass == RSURFPASS_BACKGROUND)
2161 // distorted background
2162 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2164 mode = SHADERMODE_WATER;
2165 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2166 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2167 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2169 // this is the right thing to do for wateralpha
2170 GL_BlendFunc(GL_ONE, GL_ZERO);
2171 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2175 // this is the right thing to do for entity alpha
2176 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2177 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2180 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2182 mode = SHADERMODE_REFRACTION;
2183 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2184 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2185 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2186 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2190 mode = SHADERMODE_GENERIC;
2191 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2192 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2193 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2195 if (vid.allowalphatocoverage)
2196 GL_AlphaToCoverage(false);
2198 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2200 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2202 switch(rsurface.texture->offsetmapping)
2204 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2205 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2206 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207 case OFFSETMAPPING_OFF: break;
2210 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2211 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2212 // normalmap (deferred prepass), may use alpha test on diffuse
2213 mode = SHADERMODE_DEFERREDGEOMETRY;
2214 GL_BlendFunc(GL_ONE, GL_ZERO);
2215 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2216 if (vid.allowalphatocoverage)
2217 GL_AlphaToCoverage(false);
2219 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2221 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2223 switch(rsurface.texture->offsetmapping)
2225 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2226 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2227 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2228 case OFFSETMAPPING_OFF: break;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2232 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2233 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2234 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2236 mode = SHADERMODE_LIGHTSOURCE;
2237 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2238 permutation |= SHADERPERMUTATION_CUBEFILTER;
2239 if (diffusescale > 0)
2240 permutation |= SHADERPERMUTATION_DIFFUSE;
2241 if (specularscale > 0)
2242 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2243 if (r_refdef.fogenabled)
2244 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2245 if (rsurface.texture->colormapping)
2246 permutation |= SHADERPERMUTATION_COLORMAPPING;
2247 if (r_shadow_usingshadowmap2d)
2249 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2250 if(r_shadow_shadowmapvsdct)
2251 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2253 if (r_shadow_shadowmap2ddepthbuffer)
2254 permutation |= SHADERPERMUTATION_DEPTHRGB;
2256 if (rsurface.texture->reflectmasktexture)
2257 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2258 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2259 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2260 if (vid.allowalphatocoverage)
2261 GL_AlphaToCoverage(false);
2263 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2265 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2267 switch(rsurface.texture->offsetmapping)
2269 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2270 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2271 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272 case OFFSETMAPPING_OFF: break;
2275 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2276 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2277 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2278 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2279 // unshaded geometry (fullbright or ambient model lighting)
2280 mode = SHADERMODE_FLATCOLOR;
2281 ambientscale = diffusescale = specularscale = 0;
2282 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2283 permutation |= SHADERPERMUTATION_GLOW;
2284 if (r_refdef.fogenabled)
2285 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2286 if (rsurface.texture->colormapping)
2287 permutation |= SHADERPERMUTATION_COLORMAPPING;
2288 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2290 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2291 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2293 if (r_shadow_shadowmap2ddepthbuffer)
2294 permutation |= SHADERPERMUTATION_DEPTHRGB;
2296 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2297 permutation |= SHADERPERMUTATION_REFLECTION;
2298 if (rsurface.texture->reflectmasktexture)
2299 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2300 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2301 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2302 // when using alphatocoverage, we don't need alphakill
2303 if (vid.allowalphatocoverage)
2305 if (r_transparent_alphatocoverage.integer)
2307 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2308 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2311 GL_AlphaToCoverage(false);
2314 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2316 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2318 switch(rsurface.texture->offsetmapping)
2320 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2321 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323 case OFFSETMAPPING_OFF: break;
2326 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2327 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2328 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2329 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2330 // directional model lighting
2331 mode = SHADERMODE_LIGHTDIRECTION;
2332 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2333 permutation |= SHADERPERMUTATION_GLOW;
2334 permutation |= SHADERPERMUTATION_DIFFUSE;
2335 if (specularscale > 0)
2336 permutation |= SHADERPERMUTATION_SPECULAR;
2337 if (r_refdef.fogenabled)
2338 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2339 if (rsurface.texture->colormapping)
2340 permutation |= SHADERPERMUTATION_COLORMAPPING;
2341 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2343 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2344 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2346 if (r_shadow_shadowmap2ddepthbuffer)
2347 permutation |= SHADERPERMUTATION_DEPTHRGB;
2349 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2350 permutation |= SHADERPERMUTATION_REFLECTION;
2351 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2352 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2353 if (rsurface.texture->reflectmasktexture)
2354 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2355 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2357 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2358 if (r_shadow_bouncegriddirectional)
2359 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2361 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2362 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2363 // when using alphatocoverage, we don't need alphakill
2364 if (vid.allowalphatocoverage)
2366 if (r_transparent_alphatocoverage.integer)
2368 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2369 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2372 GL_AlphaToCoverage(false);
2375 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2377 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2379 switch(rsurface.texture->offsetmapping)
2381 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2382 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2383 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384 case OFFSETMAPPING_OFF: break;
2387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2388 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2390 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2391 // ambient model lighting
2392 mode = SHADERMODE_LIGHTDIRECTION;
2393 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2394 permutation |= SHADERPERMUTATION_GLOW;
2395 if (r_refdef.fogenabled)
2396 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2397 if (rsurface.texture->colormapping)
2398 permutation |= SHADERPERMUTATION_COLORMAPPING;
2399 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2401 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2402 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2404 if (r_shadow_shadowmap2ddepthbuffer)
2405 permutation |= SHADERPERMUTATION_DEPTHRGB;
2407 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2408 permutation |= SHADERPERMUTATION_REFLECTION;
2409 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2410 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2411 if (rsurface.texture->reflectmasktexture)
2412 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2413 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2415 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2416 if (r_shadow_bouncegriddirectional)
2417 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2420 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 // when using alphatocoverage, we don't need alphakill
2422 if (vid.allowalphatocoverage)
2424 if (r_transparent_alphatocoverage.integer)
2426 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2427 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2430 GL_AlphaToCoverage(false);
2435 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2437 switch(rsurface.texture->offsetmapping)
2439 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2440 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2441 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2442 case OFFSETMAPPING_OFF: break;
2445 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2446 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2447 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2448 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2450 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2451 permutation |= SHADERPERMUTATION_GLOW;
2452 if (r_refdef.fogenabled)
2453 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2454 if (rsurface.texture->colormapping)
2455 permutation |= SHADERPERMUTATION_COLORMAPPING;
2456 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2458 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2459 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2461 if (r_shadow_shadowmap2ddepthbuffer)
2462 permutation |= SHADERPERMUTATION_DEPTHRGB;
2464 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2465 permutation |= SHADERPERMUTATION_REFLECTION;
2466 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2467 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2468 if (rsurface.texture->reflectmasktexture)
2469 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2470 if (FAKELIGHT_ENABLED)
2472 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2473 mode = SHADERMODE_FAKELIGHT;
2474 permutation |= SHADERPERMUTATION_DIFFUSE;
2475 if (specularscale > 0)
2476 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2478 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2480 // deluxemapping (light direction texture)
2481 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2482 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2484 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2485 permutation |= SHADERPERMUTATION_DIFFUSE;
2486 if (specularscale > 0)
2487 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2489 else if (r_glsl_deluxemapping.integer >= 2)
2491 // fake deluxemapping (uniform light direction in tangentspace)
2492 if (rsurface.uselightmaptexture)
2493 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2495 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2496 permutation |= SHADERPERMUTATION_DIFFUSE;
2497 if (specularscale > 0)
2498 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2500 else if (rsurface.uselightmaptexture)
2502 // ordinary lightmapping (q1bsp, q3bsp)
2503 mode = SHADERMODE_LIGHTMAP;
2507 // ordinary vertex coloring (q3bsp)
2508 mode = SHADERMODE_VERTEXCOLOR;
2510 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2512 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2513 if (r_shadow_bouncegriddirectional)
2514 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2516 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2517 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2518 // when using alphatocoverage, we don't need alphakill
2519 if (vid.allowalphatocoverage)
2521 if (r_transparent_alphatocoverage.integer)
2523 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2524 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2527 GL_AlphaToCoverage(false);
2530 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2531 colormod = dummy_colormod;
2532 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2533 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2534 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2535 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2536 switch(vid.renderpath)
2538 case RENDERPATH_D3D9:
2540 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2541 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2542 R_SetupShader_SetPermutationHLSL(mode, permutation);
2543 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2544 if (mode == SHADERMODE_LIGHTSOURCE)
2546 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2547 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2551 if (mode == SHADERMODE_LIGHTDIRECTION)
2553 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2556 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2557 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2558 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2559 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2560 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2562 if (mode == SHADERMODE_LIGHTSOURCE)
2564 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2565 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2566 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2567 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2568 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2570 // additive passes are only darkened by fog, not tinted
2571 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2572 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2576 if (mode == SHADERMODE_FLATCOLOR)
2578 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2580 else if (mode == SHADERMODE_LIGHTDIRECTION)
2582 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]);
2583 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2584 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);
2585 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2586 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2587 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2588 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2592 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2593 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2594 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);
2595 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2596 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2598 // additive passes are only darkened by fog, not tinted
2599 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2600 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2602 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2603 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);
2604 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2605 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2606 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2607 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2608 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2609 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2610 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2611 if (mode == SHADERMODE_WATER)
2612 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2614 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2615 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2616 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2617 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2618 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2619 if (rsurface.texture->pantstexture)
2620 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2622 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2623 if (rsurface.texture->shirttexture)
2624 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2627 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2628 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2629 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2630 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2631 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2632 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2633 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2634 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2635 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2637 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2638 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2639 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2640 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2642 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2643 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2644 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2645 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2646 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2647 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2648 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2649 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2650 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2651 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2652 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2653 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2654 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2655 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2656 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2657 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2658 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2659 if (rsurfacepass == RSURFPASS_BACKGROUND)
2661 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2662 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2663 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2667 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
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_shadowmap2ddepthtexture);
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) | BATCHNEED_ALLOWMULTIDRAW, 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);
2701 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2702 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2703 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2707 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) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2708 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2710 // this has to be after RSurf_PrepareVerticesForBatch
2711 if (rsurface.batchskeletaltransform3x4)
2712 permutation |= SHADERPERMUTATION_SKELETAL;
2713 R_SetupShader_SetPermutationGLSL(mode, permutation);
2714 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2715 if (mode == SHADERMODE_LIGHTSOURCE)
2717 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2718 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2719 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2720 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2721 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2722 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);
2724 // additive passes are only darkened by fog, not tinted
2725 if (r_glsl_permutation->loc_FogColor >= 0)
2726 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2727 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);
2731 if (mode == SHADERMODE_FLATCOLOR)
2733 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2735 else if (mode == SHADERMODE_LIGHTDIRECTION)
2737 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]);
2738 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]);
2739 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);
2740 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2741 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2742 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]);
2743 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]);
2747 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]);
2748 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]);
2749 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);
2750 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2751 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2753 // additive passes are only darkened by fog, not tinted
2754 if (r_glsl_permutation->loc_FogColor >= 0)
2756 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2757 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2759 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2761 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);
2762 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2763 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2764 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]);
2765 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]);
2766 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2767 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2768 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);
2769 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]);
2771 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2772 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2773 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2774 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]);
2775 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]);
2777 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2778 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2779 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2780 if (r_glsl_permutation->loc_Color_Pants >= 0)
2782 if (rsurface.texture->pantstexture)
2783 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2785 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2787 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2789 if (rsurface.texture->shirttexture)
2790 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2792 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2794 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]);
2795 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2796 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2797 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2798 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2799 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2800 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2801 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2802 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2804 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2805 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2806 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]);
2807 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2808 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);}
2809 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2811 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2812 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2813 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2814 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2815 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2816 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2817 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2818 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2819 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2820 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2821 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2822 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2823 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2824 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2825 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);
2826 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2827 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2828 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2829 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2830 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2831 if (rsurfacepass == RSURFPASS_BACKGROUND)
2833 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);
2834 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);
2835 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);
2839 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);
2841 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2842 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2843 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2844 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2846 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2847 if (rsurface.rtlight)
2849 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2850 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2853 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2854 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.batchskeletalnumtransforms > 0)
2855 qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.batchskeletalnumtransforms*3, rsurface.batchskeletaltransform3x4);
2858 case RENDERPATH_GL11:
2859 case RENDERPATH_GL13:
2860 case RENDERPATH_GLES1:
2862 case RENDERPATH_SOFT:
2863 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) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2864 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2865 R_SetupShader_SetPermutationSoft(mode, permutation);
2866 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2867 if (mode == SHADERMODE_LIGHTSOURCE)
2869 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2870 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2871 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2872 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2876 // additive passes are only darkened by fog, not tinted
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2878 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2882 if (mode == SHADERMODE_FLATCOLOR)
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2886 else if (mode == SHADERMODE_LIGHTDIRECTION)
2888 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]);
2889 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2890 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);
2891 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2893 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]);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2898 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2900 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);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2902 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2904 // additive passes are only darkened by fog, not tinted
2905 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2906 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2908 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2909 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);
2910 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2911 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2912 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]);
2913 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]);
2914 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2915 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2916 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2917 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2919 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2920 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2921 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2922 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2923 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]);
2925 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2926 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2927 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2928 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2930 if (rsurface.texture->pantstexture)
2931 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2935 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2937 if (rsurface.texture->shirttexture)
2938 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2940 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2942 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2943 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2944 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2945 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2946 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2947 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2948 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2949 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2950 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2952 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2953 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2954 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2955 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2957 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2958 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2959 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2960 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2961 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2962 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2963 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2964 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2965 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2966 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2967 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2968 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2969 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2970 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2971 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2972 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2973 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2974 if (rsurfacepass == RSURFPASS_BACKGROUND)
2976 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2977 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2978 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2982 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2984 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2985 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2986 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2987 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2989 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2990 if (rsurface.rtlight)
2992 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2993 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3000 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3002 // select a permutation of the lighting shader appropriate to this
3003 // combination of texture, entity, light source, and fogging, only use the
3004 // minimum features necessary to avoid wasting rendering time in the
3005 // fragment shader on features that are not being used
3006 unsigned int permutation = 0;
3007 unsigned int mode = 0;
3008 const float *lightcolorbase = rtlight->currentcolor;
3009 float ambientscale = rtlight->ambientscale;
3010 float diffusescale = rtlight->diffusescale;
3011 float specularscale = rtlight->specularscale;
3012 // this is the location of the light in view space
3013 vec3_t viewlightorigin;
3014 // this transforms from view space (camera) to light space (cubemap)
3015 matrix4x4_t viewtolight;
3016 matrix4x4_t lighttoview;
3017 float viewtolight16f[16];
3019 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3020 if (rtlight->currentcubemap != r_texture_whitecube)
3021 permutation |= SHADERPERMUTATION_CUBEFILTER;
3022 if (diffusescale > 0)
3023 permutation |= SHADERPERMUTATION_DIFFUSE;
3024 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3025 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3026 if (r_shadow_usingshadowmap2d)
3028 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3029 if (r_shadow_shadowmapvsdct)
3030 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3032 if (r_shadow_shadowmap2ddepthbuffer)
3033 permutation |= SHADERPERMUTATION_DEPTHRGB;
3035 if (vid.allowalphatocoverage)
3036 GL_AlphaToCoverage(false);
3037 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3038 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3039 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3040 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3041 switch(vid.renderpath)
3043 case RENDERPATH_D3D9:
3045 R_SetupShader_SetPermutationHLSL(mode, permutation);
3046 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3047 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3048 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3049 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3050 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3051 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3052 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3053 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);
3054 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3055 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3057 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
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_shadowmap2ddepthtexture );
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 , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3076 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3077 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
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_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3086 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3087 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3088 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3090 case RENDERPATH_GL11:
3091 case RENDERPATH_GL13:
3092 case RENDERPATH_GLES1:
3094 case RENDERPATH_SOFT:
3095 R_SetupShader_SetPermutationGLSL(mode, permutation);
3096 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3097 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3098 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3099 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3100 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3101 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3102 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]);
3103 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);
3104 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3105 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3107 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3108 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3109 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3110 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3111 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3116 #define SKINFRAME_HASH 1024
3120 int loadsequence; // incremented each level change
3121 memexpandablearray_t array;
3122 skinframe_t *hash[SKINFRAME_HASH];
3125 r_skinframe_t r_skinframe;
3127 void R_SkinFrame_PrepareForPurge(void)
3129 r_skinframe.loadsequence++;
3130 // wrap it without hitting zero
3131 if (r_skinframe.loadsequence >= 200)
3132 r_skinframe.loadsequence = 1;
3135 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3139 // mark the skinframe as used for the purging code
3140 skinframe->loadsequence = r_skinframe.loadsequence;
3143 void R_SkinFrame_Purge(void)
3147 for (i = 0;i < SKINFRAME_HASH;i++)
3149 for (s = r_skinframe.hash[i];s;s = s->next)
3151 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3153 if (s->merged == s->base)
3155 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3156 R_PurgeTexture(s->stain );s->stain = NULL;
3157 R_PurgeTexture(s->merged);s->merged = NULL;
3158 R_PurgeTexture(s->base );s->base = NULL;
3159 R_PurgeTexture(s->pants );s->pants = NULL;
3160 R_PurgeTexture(s->shirt );s->shirt = NULL;
3161 R_PurgeTexture(s->nmap );s->nmap = NULL;
3162 R_PurgeTexture(s->gloss );s->gloss = NULL;
3163 R_PurgeTexture(s->glow );s->glow = NULL;
3164 R_PurgeTexture(s->fog );s->fog = NULL;
3165 R_PurgeTexture(s->reflect);s->reflect = NULL;
3166 s->loadsequence = 0;
3172 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3174 char basename[MAX_QPATH];
3176 Image_StripImageExtension(name, basename, sizeof(basename));
3178 if( last == NULL ) {
3180 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3181 item = r_skinframe.hash[hashindex];
3186 // linearly search through the hash bucket
3187 for( ; item ; item = item->next ) {
3188 if( !strcmp( item->basename, basename ) ) {
3195 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3199 char basename[MAX_QPATH];
3201 Image_StripImageExtension(name, basename, sizeof(basename));
3203 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3204 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3205 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3209 rtexture_t *dyntexture;
3210 // check whether its a dynamic texture
3211 dyntexture = CL_GetDynTexture( basename );
3212 if (!add && !dyntexture)
3214 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3215 memset(item, 0, sizeof(*item));
3216 strlcpy(item->basename, basename, sizeof(item->basename));
3217 item->base = dyntexture; // either NULL or dyntexture handle
3218 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3219 item->comparewidth = comparewidth;
3220 item->compareheight = compareheight;
3221 item->comparecrc = comparecrc;
3222 item->next = r_skinframe.hash[hashindex];
3223 r_skinframe.hash[hashindex] = item;
3225 else if (textureflags & TEXF_FORCE_RELOAD)
3227 rtexture_t *dyntexture;
3228 // check whether its a dynamic texture
3229 dyntexture = CL_GetDynTexture( basename );
3230 if (!add && !dyntexture)
3232 if (item->merged == item->base)
3233 item->merged = NULL;
3234 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3235 R_PurgeTexture(item->stain );item->stain = NULL;
3236 R_PurgeTexture(item->merged);item->merged = NULL;
3237 R_PurgeTexture(item->base );item->base = NULL;
3238 R_PurgeTexture(item->pants );item->pants = NULL;
3239 R_PurgeTexture(item->shirt );item->shirt = NULL;
3240 R_PurgeTexture(item->nmap );item->nmap = NULL;
3241 R_PurgeTexture(item->gloss );item->gloss = NULL;
3242 R_PurgeTexture(item->glow );item->glow = NULL;
3243 R_PurgeTexture(item->fog );item->fog = NULL;
3244 R_PurgeTexture(item->reflect);item->reflect = NULL;
3245 item->loadsequence = 0;
3247 else if( item->base == NULL )
3249 rtexture_t *dyntexture;
3250 // check whether its a dynamic texture
3251 // 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]
3252 dyntexture = CL_GetDynTexture( basename );
3253 item->base = dyntexture; // either NULL or dyntexture handle
3256 R_SkinFrame_MarkUsed(item);
3260 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3262 unsigned long long avgcolor[5], wsum; \
3270 for(pix = 0; pix < cnt; ++pix) \
3273 for(comp = 0; comp < 3; ++comp) \
3275 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3278 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3280 for(comp = 0; comp < 3; ++comp) \
3281 avgcolor[comp] += getpixel * w; \
3284 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3285 avgcolor[4] += getpixel; \
3287 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3289 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3290 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3291 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3292 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3295 extern cvar_t gl_picmip;
3296 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3299 unsigned char *pixels;
3300 unsigned char *bumppixels;
3301 unsigned char *basepixels = NULL;
3302 int basepixels_width = 0;
3303 int basepixels_height = 0;
3304 skinframe_t *skinframe;
3305 rtexture_t *ddsbase = NULL;
3306 qboolean ddshasalpha = false;
3307 float ddsavgcolor[4];
3308 char basename[MAX_QPATH];
3309 int miplevel = R_PicmipForFlags(textureflags);
3310 int savemiplevel = miplevel;
3314 if (cls.state == ca_dedicated)
3317 // return an existing skinframe if already loaded
3318 // if loading of the first image fails, don't make a new skinframe as it
3319 // would cause all future lookups of this to be missing
3320 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3321 if (skinframe && skinframe->base)
3324 Image_StripImageExtension(name, basename, sizeof(basename));
3326 // check for DDS texture file first
3327 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3329 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3330 if (basepixels == NULL)
3334 // FIXME handle miplevel
3336 if (developer_loading.integer)
3337 Con_Printf("loading skin \"%s\"\n", name);
3339 // we've got some pixels to store, so really allocate this new texture now
3341 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3342 textureflags &= ~TEXF_FORCE_RELOAD;
3343 skinframe->stain = NULL;
3344 skinframe->merged = NULL;
3345 skinframe->base = NULL;
3346 skinframe->pants = NULL;
3347 skinframe->shirt = NULL;
3348 skinframe->nmap = NULL;
3349 skinframe->gloss = NULL;
3350 skinframe->glow = NULL;
3351 skinframe->fog = NULL;
3352 skinframe->reflect = NULL;
3353 skinframe->hasalpha = false;
3357 skinframe->base = ddsbase;
3358 skinframe->hasalpha = ddshasalpha;
3359 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3360 if (r_loadfog && skinframe->hasalpha)
3361 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3362 //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]);
3366 basepixels_width = image_width;
3367 basepixels_height = image_height;
3368 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);
3369 if (textureflags & TEXF_ALPHA)
3371 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3373 if (basepixels[j] < 255)
3375 skinframe->hasalpha = true;
3379 if (r_loadfog && skinframe->hasalpha)
3381 // has transparent pixels
3382 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3383 for (j = 0;j < image_width * image_height * 4;j += 4)
3388 pixels[j+3] = basepixels[j+3];
3390 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3394 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3396 //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]);
3397 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3398 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3399 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3400 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3406 mymiplevel = savemiplevel;
3407 if (r_loadnormalmap)
3408 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3409 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3411 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3412 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3413 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3414 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3417 // _norm is the name used by tenebrae and has been adopted as standard
3418 if (r_loadnormalmap && skinframe->nmap == NULL)
3420 mymiplevel = savemiplevel;
3421 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3423 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3427 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3429 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3430 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3431 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3433 Mem_Free(bumppixels);
3435 else if (r_shadow_bumpscale_basetexture.value > 0)
3437 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3438 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3439 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3443 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3444 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3448 // _luma is supported only for tenebrae compatibility
3449 // _glow is the preferred name
3450 mymiplevel = savemiplevel;
3451 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3453 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3455 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3456 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 Mem_Free(pixels);pixels = NULL;
3461 mymiplevel = savemiplevel;
3462 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3464 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3466 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3467 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3473 mymiplevel = savemiplevel;
3474 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3476 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3478 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3479 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3485 mymiplevel = savemiplevel;
3486 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3488 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3490 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3491 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3497 mymiplevel = savemiplevel;
3498 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3500 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3502 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3503 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3510 Mem_Free(basepixels);
3515 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3516 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3519 unsigned char *temp1, *temp2;
3520 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->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(vabuf, sizeof(vabuf), "%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(vabuf, sizeof(vabuf), "%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->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;
3651 if (!skinframe->qpixels)
3654 if (!skinframe->qhascolormapping)
3655 colormapped = false;
3659 if (!skinframe->qgeneratebase)
3664 if (!skinframe->qgeneratemerged)
3668 width = skinframe->qwidth;
3669 height = skinframe->qheight;
3670 skindata = skinframe->qpixels;
3672 if (skinframe->qgeneratenmap)
3674 unsigned char *temp1, *temp2;
3675 skinframe->qgeneratenmap = false;
3676 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3677 temp2 = temp1 + width * height * 4;
3678 // use either a custom palette or the quake palette
3679 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3680 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3681 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3685 if (skinframe->qgenerateglow)
3687 skinframe->qgenerateglow = false;
3688 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3693 skinframe->qgeneratebase = false;
3694 skinframe->base = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%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);
3695 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3696 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3700 skinframe->qgeneratemerged = false;
3701 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);
3704 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3706 Mem_Free(skinframe->qpixels);
3707 skinframe->qpixels = NULL;
3711 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)
3714 skinframe_t *skinframe;
3717 if (cls.state == ca_dedicated)
3720 // if already loaded just return it, otherwise make a new skinframe
3721 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3722 if (skinframe->base)
3724 textureflags &= ~TEXF_FORCE_RELOAD;
3726 skinframe->stain = NULL;
3727 skinframe->merged = NULL;
3728 skinframe->base = NULL;
3729 skinframe->pants = NULL;
3730 skinframe->shirt = NULL;
3731 skinframe->nmap = NULL;
3732 skinframe->gloss = NULL;
3733 skinframe->glow = NULL;
3734 skinframe->fog = NULL;
3735 skinframe->reflect = NULL;
3736 skinframe->hasalpha = false;
3738 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3742 if (developer_loading.integer)
3743 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3745 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3746 if (textureflags & TEXF_ALPHA)
3748 for (i = 0;i < width * height;i++)
3750 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3752 skinframe->hasalpha = true;
3756 if (r_loadfog && skinframe->hasalpha)
3757 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3760 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3761 //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]);
3766 skinframe_t *R_SkinFrame_LoadMissing(void)
3768 skinframe_t *skinframe;
3770 if (cls.state == ca_dedicated)
3773 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3774 skinframe->stain = NULL;
3775 skinframe->merged = NULL;
3776 skinframe->base = NULL;
3777 skinframe->pants = NULL;
3778 skinframe->shirt = NULL;
3779 skinframe->nmap = NULL;
3780 skinframe->gloss = NULL;
3781 skinframe->glow = NULL;
3782 skinframe->fog = NULL;
3783 skinframe->reflect = NULL;
3784 skinframe->hasalpha = false;
3786 skinframe->avgcolor[0] = rand() / RAND_MAX;
3787 skinframe->avgcolor[1] = rand() / RAND_MAX;
3788 skinframe->avgcolor[2] = rand() / RAND_MAX;
3789 skinframe->avgcolor[3] = 1;
3794 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3795 typedef struct suffixinfo_s
3798 qboolean flipx, flipy, flipdiagonal;
3801 static suffixinfo_t suffix[3][6] =
3804 {"px", false, false, false},
3805 {"nx", false, false, false},
3806 {"py", false, false, false},
3807 {"ny", false, false, false},
3808 {"pz", false, false, false},
3809 {"nz", false, false, false}
3812 {"posx", false, false, false},
3813 {"negx", false, false, false},
3814 {"posy", false, false, false},
3815 {"negy", false, false, false},
3816 {"posz", false, false, false},
3817 {"negz", false, false, false}
3820 {"rt", true, false, true},
3821 {"lf", false, true, true},
3822 {"ft", true, true, false},
3823 {"bk", false, false, false},
3824 {"up", true, false, true},
3825 {"dn", true, false, true}
3829 static int componentorder[4] = {0, 1, 2, 3};
3831 static rtexture_t *R_LoadCubemap(const char *basename)
3833 int i, j, cubemapsize;
3834 unsigned char *cubemappixels, *image_buffer;
3835 rtexture_t *cubemaptexture;
3837 // must start 0 so the first loadimagepixels has no requested width/height
3839 cubemappixels = NULL;
3840 cubemaptexture = NULL;
3841 // keep trying different suffix groups (posx, px, rt) until one loads
3842 for (j = 0;j < 3 && !cubemappixels;j++)
3844 // load the 6 images in the suffix group
3845 for (i = 0;i < 6;i++)
3847 // generate an image name based on the base and and suffix
3848 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3850 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3852 // an image loaded, make sure width and height are equal
3853 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3855 // if this is the first image to load successfully, allocate the cubemap memory
3856 if (!cubemappixels && image_width >= 1)
3858 cubemapsize = image_width;
3859 // note this clears to black, so unavailable sides are black
3860 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3862 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3864 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);
3867 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3869 Mem_Free(image_buffer);
3873 // if a cubemap loaded, upload it
3876 if (developer_loading.integer)
3877 Con_Printf("loading cubemap \"%s\"\n", basename);
3879 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);
3880 Mem_Free(cubemappixels);
3884 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3885 if (developer_loading.integer)
3887 Con_Printf("(tried tried images ");
3888 for (j = 0;j < 3;j++)
3889 for (i = 0;i < 6;i++)
3890 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3891 Con_Print(" and was unable to find any of them).\n");
3894 return cubemaptexture;
3897 rtexture_t *R_GetCubemap(const char *basename)
3900 for (i = 0;i < r_texture_numcubemaps;i++)
3901 if (r_texture_cubemaps[i] != NULL)
3902 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3903 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3904 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3905 return r_texture_whitecube;
3906 r_texture_numcubemaps++;
3907 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3908 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3909 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3910 return r_texture_cubemaps[i]->texture;
3913 static void R_Main_FreeViewCache(void)
3915 if (r_refdef.viewcache.entityvisible)
3916 Mem_Free(r_refdef.viewcache.entityvisible);
3917 if (r_refdef.viewcache.world_pvsbits)
3918 Mem_Free(r_refdef.viewcache.world_pvsbits);
3919 if (r_refdef.viewcache.world_leafvisible)
3920 Mem_Free(r_refdef.viewcache.world_leafvisible);
3921 if (r_refdef.viewcache.world_surfacevisible)
3922 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3923 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3926 static void R_Main_ResizeViewCache(void)
3928 int numentities = r_refdef.scene.numentities;
3929 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3930 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3931 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3932 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3933 if (r_refdef.viewcache.maxentities < numentities)
3935 r_refdef.viewcache.maxentities = numentities;
3936 if (r_refdef.viewcache.entityvisible)
3937 Mem_Free(r_refdef.viewcache.entityvisible);
3938 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3940 if (r_refdef.viewcache.world_numclusters != numclusters)
3942 r_refdef.viewcache.world_numclusters = numclusters;
3943 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3944 if (r_refdef.viewcache.world_pvsbits)
3945 Mem_Free(r_refdef.viewcache.world_pvsbits);
3946 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3948 if (r_refdef.viewcache.world_numleafs != numleafs)
3950 r_refdef.viewcache.world_numleafs = numleafs;
3951 if (r_refdef.viewcache.world_leafvisible)
3952 Mem_Free(r_refdef.viewcache.world_leafvisible);
3953 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3955 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3957 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3958 if (r_refdef.viewcache.world_surfacevisible)
3959 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3960 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3964 extern rtexture_t *loadingscreentexture;
3965 static void gl_main_start(void)
3967 loadingscreentexture = NULL;
3968 r_texture_blanknormalmap = NULL;
3969 r_texture_white = NULL;
3970 r_texture_grey128 = NULL;
3971 r_texture_black = NULL;
3972 r_texture_whitecube = NULL;
3973 r_texture_normalizationcube = NULL;
3974 r_texture_fogattenuation = NULL;
3975 r_texture_fogheighttexture = NULL;
3976 r_texture_gammaramps = NULL;
3977 r_texture_numcubemaps = 0;
3979 r_loaddds = r_texture_dds_load.integer != 0;
3980 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3982 switch(vid.renderpath)
3984 case RENDERPATH_GL20:
3985 case RENDERPATH_D3D9:
3986 case RENDERPATH_D3D10:
3987 case RENDERPATH_D3D11:
3988 case RENDERPATH_SOFT:
3989 case RENDERPATH_GLES2:
3990 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991 Cvar_SetValueQuick(&gl_combine, 1);
3992 Cvar_SetValueQuick(&r_glsl, 1);
3993 r_loadnormalmap = true;
3997 case RENDERPATH_GL13:
3998 case RENDERPATH_GLES1:
3999 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4000 Cvar_SetValueQuick(&gl_combine, 1);
4001 Cvar_SetValueQuick(&r_glsl, 0);
4002 r_loadnormalmap = false;
4003 r_loadgloss = false;
4006 case RENDERPATH_GL11:
4007 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4008 Cvar_SetValueQuick(&gl_combine, 0);
4009 Cvar_SetValueQuick(&r_glsl, 0);
4010 r_loadnormalmap = false;
4011 r_loadgloss = false;
4017 R_FrameData_Reset();
4021 memset(r_queries, 0, sizeof(r_queries));
4023 r_qwskincache = NULL;
4024 r_qwskincache_size = 0;
4026 // due to caching of texture_t references, the collision cache must be reset
4027 Collision_Cache_Reset(true);
4029 // set up r_skinframe loading system for textures
4030 memset(&r_skinframe, 0, sizeof(r_skinframe));
4031 r_skinframe.loadsequence = 1;
4032 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4034 r_main_texturepool = R_AllocTexturePool();
4035 R_BuildBlankTextures();
4037 if (vid.support.arb_texture_cube_map)
4040 R_BuildNormalizationCube();
4042 r_texture_fogattenuation = NULL;
4043 r_texture_fogheighttexture = NULL;
4044 r_texture_gammaramps = NULL;
4045 //r_texture_fogintensity = NULL;
4046 memset(&r_fb, 0, sizeof(r_fb));
4047 r_glsl_permutation = NULL;
4048 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4049 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4050 glslshaderstring = NULL;
4052 r_hlsl_permutation = NULL;
4053 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4054 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4056 hlslshaderstring = NULL;
4057 memset(&r_svbsp, 0, sizeof (r_svbsp));
4059 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4060 r_texture_numcubemaps = 0;
4062 r_refdef.fogmasktable_density = 0;
4065 static void gl_main_shutdown(void)
4068 R_FrameData_Reset();
4070 R_Main_FreeViewCache();
4072 switch(vid.renderpath)
4074 case RENDERPATH_GL11:
4075 case RENDERPATH_GL13:
4076 case RENDERPATH_GL20:
4077 case RENDERPATH_GLES1:
4078 case RENDERPATH_GLES2:
4079 #ifdef GL_SAMPLES_PASSED_ARB
4081 qglDeleteQueriesARB(r_maxqueries, r_queries);
4084 case RENDERPATH_D3D9:
4085 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4087 case RENDERPATH_D3D10:
4088 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090 case RENDERPATH_D3D11:
4091 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4093 case RENDERPATH_SOFT:
4099 memset(r_queries, 0, sizeof(r_queries));
4101 r_qwskincache = NULL;
4102 r_qwskincache_size = 0;
4104 // clear out the r_skinframe state
4105 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4106 memset(&r_skinframe, 0, sizeof(r_skinframe));
4109 Mem_Free(r_svbsp.nodes);
4110 memset(&r_svbsp, 0, sizeof (r_svbsp));
4111 R_FreeTexturePool(&r_main_texturepool);
4112 loadingscreentexture = NULL;
4113 r_texture_blanknormalmap = NULL;
4114 r_texture_white = NULL;
4115 r_texture_grey128 = NULL;
4116 r_texture_black = NULL;
4117 r_texture_whitecube = NULL;
4118 r_texture_normalizationcube = NULL;
4119 r_texture_fogattenuation = NULL;
4120 r_texture_fogheighttexture = NULL;
4121 r_texture_gammaramps = NULL;
4122 r_texture_numcubemaps = 0;
4123 //r_texture_fogintensity = NULL;
4124 memset(&r_fb, 0, sizeof(r_fb));
4127 r_glsl_permutation = NULL;
4128 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4130 glslshaderstring = NULL;
4132 r_hlsl_permutation = NULL;
4133 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4134 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4136 hlslshaderstring = NULL;
4139 static void gl_main_newmap(void)
4141 // FIXME: move this code to client
4142 char *entities, entname[MAX_QPATH];
4144 Mem_Free(r_qwskincache);
4145 r_qwskincache = NULL;
4146 r_qwskincache_size = 0;
4149 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4150 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4152 CL_ParseEntityLump(entities);
4156 if (cl.worldmodel->brush.entities)
4157 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4159 R_Main_FreeViewCache();
4161 R_FrameData_Reset();
4164 void GL_Main_Init(void)
4166 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4168 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4169 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4170 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4171 if (gamemode == GAME_NEHAHRA)
4173 Cvar_RegisterVariable (&gl_fogenable);
4174 Cvar_RegisterVariable (&gl_fogdensity);
4175 Cvar_RegisterVariable (&gl_fogred);
4176 Cvar_RegisterVariable (&gl_foggreen);
4177 Cvar_RegisterVariable (&gl_fogblue);
4178 Cvar_RegisterVariable (&gl_fogstart);
4179 Cvar_RegisterVariable (&gl_fogend);
4180 Cvar_RegisterVariable (&gl_skyclip);
4182 Cvar_RegisterVariable(&r_motionblur);
4183 Cvar_RegisterVariable(&r_damageblur);
4184 Cvar_RegisterVariable(&r_motionblur_averaging);
4185 Cvar_RegisterVariable(&r_motionblur_randomize);
4186 Cvar_RegisterVariable(&r_motionblur_minblur);
4187 Cvar_RegisterVariable(&r_motionblur_maxblur);
4188 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4189 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4190 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4191 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4192 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4193 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4194 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4195 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4196 Cvar_RegisterVariable(&r_equalize_entities_by);
4197 Cvar_RegisterVariable(&r_equalize_entities_to);
4198 Cvar_RegisterVariable(&r_depthfirst);
4199 Cvar_RegisterVariable(&r_useinfinitefarclip);
4200 Cvar_RegisterVariable(&r_farclip_base);
4201 Cvar_RegisterVariable(&r_farclip_world);
4202 Cvar_RegisterVariable(&r_nearclip);
4203 Cvar_RegisterVariable(&r_deformvertexes);
4204 Cvar_RegisterVariable(&r_transparent);
4205 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4206 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4207 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4208 Cvar_RegisterVariable(&r_showoverdraw);
4209 Cvar_RegisterVariable(&r_showbboxes);
4210 Cvar_RegisterVariable(&r_showsurfaces);
4211 Cvar_RegisterVariable(&r_showtris);
4212 Cvar_RegisterVariable(&r_shownormals);
4213 Cvar_RegisterVariable(&r_showlighting);
4214 Cvar_RegisterVariable(&r_showshadowvolumes);
4215 Cvar_RegisterVariable(&r_showcollisionbrushes);
4216 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4217 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4218 Cvar_RegisterVariable(&r_showdisabledepthtest);
4219 Cvar_RegisterVariable(&r_drawportals);
4220 Cvar_RegisterVariable(&r_drawentities);
4221 Cvar_RegisterVariable(&r_draw2d);
4222 Cvar_RegisterVariable(&r_drawworld);
4223 Cvar_RegisterVariable(&r_cullentities_trace);
4224 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4225 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4226 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4227 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4228 Cvar_RegisterVariable(&r_sortentities);
4229 Cvar_RegisterVariable(&r_drawviewmodel);
4230 Cvar_RegisterVariable(&r_drawexteriormodel);
4231 Cvar_RegisterVariable(&r_speeds);
4232 Cvar_RegisterVariable(&r_fullbrights);
4233 Cvar_RegisterVariable(&r_wateralpha);
4234 Cvar_RegisterVariable(&r_dynamic);
4235 Cvar_RegisterVariable(&r_fakelight);
4236 Cvar_RegisterVariable(&r_fakelight_intensity);
4237 Cvar_RegisterVariable(&r_fullbright);
4238 Cvar_RegisterVariable(&r_shadows);
4239 Cvar_RegisterVariable(&r_shadows_darken);
4240 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4241 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4242 Cvar_RegisterVariable(&r_shadows_throwdistance);
4243 Cvar_RegisterVariable(&r_shadows_throwdirection);
4244 Cvar_RegisterVariable(&r_shadows_focus);
4245 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4246 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4247 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4248 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4249 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4250 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4251 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4252 Cvar_RegisterVariable(&r_fog_exp2);
4253 Cvar_RegisterVariable(&r_fog_clear);
4254 Cvar_RegisterVariable(&r_drawfog);
4255 Cvar_RegisterVariable(&r_transparentdepthmasking);
4256 Cvar_RegisterVariable(&r_transparent_sortmindist);
4257 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4258 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4259 Cvar_RegisterVariable(&r_texture_dds_load);
4260 Cvar_RegisterVariable(&r_texture_dds_save);
4261 Cvar_RegisterVariable(&r_textureunits);
4262 Cvar_RegisterVariable(&gl_combine);
4263 Cvar_RegisterVariable(&r_usedepthtextures);
4264 Cvar_RegisterVariable(&r_viewfbo);
4265 Cvar_RegisterVariable(&r_viewscale);
4266 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4267 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4268 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4269 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4270 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4271 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4272 Cvar_RegisterVariable(&r_glsl);
4273 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4274 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4275 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4276 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4277 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4278 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4279 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4280 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4281 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4282 Cvar_RegisterVariable(&r_glsl_postprocess);
4283 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4284 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4285 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4286 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4287 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4288 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4289 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4290 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4291 Cvar_RegisterVariable(&r_celshading);
4292 Cvar_RegisterVariable(&r_celoutlines);
4294 Cvar_RegisterVariable(&r_water);
4295 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4296 Cvar_RegisterVariable(&r_water_clippingplanebias);
4297 Cvar_RegisterVariable(&r_water_refractdistort);
4298 Cvar_RegisterVariable(&r_water_reflectdistort);
4299 Cvar_RegisterVariable(&r_water_scissormode);
4300 Cvar_RegisterVariable(&r_water_lowquality);
4301 Cvar_RegisterVariable(&r_water_hideplayer);
4302 Cvar_RegisterVariable(&r_water_fbo);
4304 Cvar_RegisterVariable(&r_lerpsprites);
4305 Cvar_RegisterVariable(&r_lerpmodels);
4306 Cvar_RegisterVariable(&r_lerplightstyles);
4307 Cvar_RegisterVariable(&r_waterscroll);
4308 Cvar_RegisterVariable(&r_bloom);
4309 Cvar_RegisterVariable(&r_bloom_colorscale);
4310 Cvar_RegisterVariable(&r_bloom_brighten);
4311 Cvar_RegisterVariable(&r_bloom_blur);
4312 Cvar_RegisterVariable(&r_bloom_resolution);
4313 Cvar_RegisterVariable(&r_bloom_colorexponent);
4314 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4315 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4316 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4317 Cvar_RegisterVariable(&r_hdr_glowintensity);
4318 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4319 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4320 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4321 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4322 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4323 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4324 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4325 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4326 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4327 Cvar_RegisterVariable(&developer_texturelogging);
4328 Cvar_RegisterVariable(&gl_lightmaps);
4329 Cvar_RegisterVariable(&r_test);
4330 Cvar_RegisterVariable(&r_batch_multidraw);
4331 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4332 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4333 Cvar_RegisterVariable(&r_glsl_skeletal);
4334 Cvar_RegisterVariable(&r_glsl_saturation);
4335 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4336 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4337 Cvar_RegisterVariable(&r_framedatasize);
4338 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4339 Cvar_SetValue("r_fullbrights", 0);
4340 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4343 void Render_Init(void)
4356 R_LightningBeams_Init();
4366 extern char *ENGINE_EXTENSIONS;
4369 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4370 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4371 gl_version = (const char *)qglGetString(GL_VERSION);
4372 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4376 if (!gl_platformextensions)
4377 gl_platformextensions = "";
4379 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4380 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4381 Con_Printf("GL_VERSION: %s\n", gl_version);
4382 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4383 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4385 VID_CheckExtensions();
4387 // LordHavoc: report supported extensions
4388 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4390 // clear to black (loading plaque will be seen over this)
4391 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4395 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4399 if (r_trippy.integer)
4401 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4403 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4406 p = r_refdef.view.frustum + i;
4411 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4415 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4419 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4423 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4427 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4431 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4435 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4439 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4447 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4451 if (r_trippy.integer)
4453 for (i = 0;i < numplanes;i++)
4460 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4464 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4468 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4472 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4476 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4480 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4484 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4488 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4496 //==================================================================================
4498 // LordHavoc: this stores temporary data used within the same frame
4500 typedef struct r_framedata_mem_s
4502 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4503 size_t size; // how much usable space
4504 size_t current; // how much space in use
4505 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4506 size_t wantedsize; // how much space was allocated
4507 unsigned char *data; // start of real data (16byte aligned)
4511 static r_framedata_mem_t *r_framedata_mem;
4513 void R_FrameData_Reset(void)
4515 while (r_framedata_mem)
4517 r_framedata_mem_t *next = r_framedata_mem->purge;
4518 Mem_Free(r_framedata_mem);
4519 r_framedata_mem = next;
4523 static void R_FrameData_Resize(void)
4526 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4527 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4528 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4530 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4531 newmem->wantedsize = wantedsize;
4532 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4533 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4534 newmem->current = 0;
4536 newmem->purge = r_framedata_mem;
4537 r_framedata_mem = newmem;
4541 void R_FrameData_NewFrame(void)
4543 R_FrameData_Resize();
4544 if (!r_framedata_mem)
4546 // if we ran out of space on the last frame, free the old memory now
4547 while (r_framedata_mem->purge)
4549 // repeatedly remove the second item in the list, leaving only head
4550 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4551 Mem_Free(r_framedata_mem->purge);
4552 r_framedata_mem->purge = next;
4554 // reset the current mem pointer
4555 r_framedata_mem->current = 0;
4556 r_framedata_mem->mark = 0;
4559 void *R_FrameData_Alloc(size_t size)
4563 // align to 16 byte boundary - the data pointer is already aligned, so we
4564 // only need to ensure the size of every allocation is also aligned
4565 size = (size + 15) & ~15;
4567 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4569 // emergency - we ran out of space, allocate more memory
4570 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4571 R_FrameData_Resize();
4574 data = r_framedata_mem->data + r_framedata_mem->current;
4575 r_framedata_mem->current += size;
4577 // count the usage for stats
4578 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4579 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4581 return (void *)data;
4584 void *R_FrameData_Store(size_t size, void *data)
4586 void *d = R_FrameData_Alloc(size);
4588 memcpy(d, data, size);
4592 void R_FrameData_SetMark(void)
4594 if (!r_framedata_mem)
4596 r_framedata_mem->mark = r_framedata_mem->current;
4599 void R_FrameData_ReturnToMark(void)
4601 if (!r_framedata_mem)
4603 r_framedata_mem->current = r_framedata_mem->mark;
4606 //==================================================================================
4608 // LordHavoc: animcache originally written by Echon, rewritten since then
4611 * Animation cache prevents re-generating mesh data for an animated model
4612 * multiple times in one frame for lighting, shadowing, reflections, etc.
4615 void R_AnimCache_Free(void)
4619 void R_AnimCache_ClearCache(void)
4622 entity_render_t *ent;
4624 for (i = 0;i < r_refdef.scene.numentities;i++)
4626 ent = r_refdef.scene.entities[i];
4627 ent->animcache_vertex3f = NULL;
4628 ent->animcache_normal3f = NULL;
4629 ent->animcache_svector3f = NULL;
4630 ent->animcache_tvector3f = NULL;
4631 ent->animcache_vertexmesh = NULL;
4632 ent->animcache_vertex3fbuffer = NULL;
4633 ent->animcache_vertexmeshbuffer = NULL;
4634 ent->animcache_skeletaltransform3x4 = NULL;
4638 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4642 // check if we need the meshbuffers
4643 if (!vid.useinterleavedarrays)
4646 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4647 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4648 // TODO: upload vertex3f buffer?
4649 if (ent->animcache_vertexmesh)
4651 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4652 for (i = 0;i < numvertices;i++)
4653 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4654 if (ent->animcache_svector3f)
4655 for (i = 0;i < numvertices;i++)
4656 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4657 if (ent->animcache_tvector3f)
4658 for (i = 0;i < numvertices;i++)
4659 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4660 if (ent->animcache_normal3f)
4661 for (i = 0;i < numvertices;i++)
4662 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4663 // TODO: upload vertexmeshbuffer?
4667 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4669 dp_model_t *model = ent->model;
4672 // cache skeletal animation data first (primarily for gpu-skinning)
4673 if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4677 const skeleton_t *skeleton = ent->skeleton;
4678 const frameblend_t *frameblend = ent->frameblend;
4679 float *boneposerelative;
4681 static float bonepose[256][12];
4682 ent->animcache_skeletaltransform3x4 = R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4683 boneposerelative = ent->animcache_skeletaltransform3x4;
4684 if (skeleton && !skeleton->relativetransforms)
4686 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4689 for (i = 0;i < model->num_bones;i++)
4691 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4692 if (model->data_bones[i].parent >= 0)
4693 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4695 memcpy(bonepose[i], m, sizeof(m));
4697 // create a relative deformation matrix to describe displacement
4698 // from the base mesh, which is used by the actual weighting
4699 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4704 for (i = 0;i < model->num_bones;i++)
4706 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4707 float lerp = frameblend[0].lerp,
4708 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4709 rx = pose7s[3] * lerp,
4710 ry = pose7s[4] * lerp,
4711 rz = pose7s[5] * lerp,
4712 rw = pose7s[6] * lerp,
4713 dx = tx*rw + ty*rz - tz*ry,
4714 dy = -tx*rz + ty*rw + tz*rx,
4715 dz = tx*ry - ty*rx + tz*rw,
4716 dw = -tx*rx - ty*ry - tz*rz,
4717 scale, sx, sy, sz, sw;
4718 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4720 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4721 float lerp = frameblend[blends].lerp,
4722 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4723 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4724 if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4733 dx += tx*qw + ty*qz - tz*qy;
4734 dy += -tx*qz + ty*qw + tz*qx;
4735 dz += tx*qy - ty*qx + tz*qw;
4736 dw += -tx*qx - ty*qy - tz*qz;
4738 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4743 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4744 m[1] = 2*(sx*ry - sw*rz);
4745 m[2] = 2*(sx*rz + sw*ry);
4746 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4747 m[4] = 2*(sx*ry + sw*rz);
4748 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4749 m[6] = 2*(sy*rz - sw*rx);
4750 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4751 m[8] = 2*(sx*rz - sw*ry);
4752 m[9] = 2*(sy*rz + sw*rx);
4753 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4754 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4755 if (i == r_skeletal_debugbone.integer)
4756 m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4757 m[3] *= r_skeletal_debugtranslatex.value;
4758 m[7] *= r_skeletal_debugtranslatey.value;
4759 m[11] *= r_skeletal_debugtranslatez.value;
4760 if (model->data_bones[i].parent >= 0)
4761 R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4763 memcpy(bonepose[i], m, sizeof(m));
4764 // create a relative deformation matrix to describe displacement
4765 // from the base mesh, which is used by the actual weighting
4766 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4771 // see if it's already cached this frame
4772 if (ent->animcache_vertex3f)
4774 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4775 if (wantnormals || wanttangents)
4777 if (ent->animcache_normal3f)
4778 wantnormals = false;
4779 if (ent->animcache_svector3f)
4780 wanttangents = false;
4781 if (wantnormals || wanttangents)
4783 numvertices = model->surfmesh.num_vertices;
4785 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4788 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4789 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4791 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4792 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4798 // see if this ent is worth caching
4799 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4801 // skip entity if the shader backend has a cheaper way
4802 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer)
4804 switch (vid.renderpath)
4806 case RENDERPATH_GL20:
4808 case RENDERPATH_GL11:
4809 case RENDERPATH_GL13:
4810 case RENDERPATH_GLES1:
4811 case RENDERPATH_GLES2:
4812 case RENDERPATH_D3D9:
4813 case RENDERPATH_D3D10:
4814 case RENDERPATH_D3D11:
4815 case RENDERPATH_SOFT:
4819 // get some memory for this entity and generate mesh data
4820 numvertices = model->surfmesh.num_vertices;
4821 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4823 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4826 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4827 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4829 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4830 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4835 void R_AnimCache_CacheVisibleEntities(void)
4838 qboolean wantnormals = true;
4839 qboolean wanttangents = !r_showsurfaces.integer;
4841 switch(vid.renderpath)
4843 case RENDERPATH_GL20:
4844 case RENDERPATH_D3D9:
4845 case RENDERPATH_D3D10:
4846 case RENDERPATH_D3D11:
4847 case RENDERPATH_GLES2:
4849 case RENDERPATH_GL11:
4850 case RENDERPATH_GL13:
4851 case RENDERPATH_GLES1:
4852 wanttangents = false;
4854 case RENDERPATH_SOFT:
4858 if (r_shownormals.integer)
4859 wanttangents = wantnormals = true;
4861 // TODO: thread this
4862 // NOTE: R_PrepareRTLights() also caches entities
4864 for (i = 0;i < r_refdef.scene.numentities;i++)
4865 if (r_refdef.viewcache.entityvisible[i])
4866 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4869 //==================================================================================
4871 extern cvar_t r_overheadsprites_pushback;
4873 static void R_View_UpdateEntityLighting (void)
4876 entity_render_t *ent;
4877 vec3_t tempdiffusenormal, avg;
4878 vec_t f, fa, fd, fdd;
4879 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4881 for (i = 0;i < r_refdef.scene.numentities;i++)
4883 ent = r_refdef.scene.entities[i];
4885 // skip unseen models
4886 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4890 if (ent->model && ent->model == cl.worldmodel)
4892 // TODO: use modellight for r_ambient settings on world?
4893 VectorSet(ent->modellight_ambient, 0, 0, 0);
4894 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4895 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4899 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4901 // aleady updated by CSQC
4902 // TODO: force modellight on BSP models in this case?
4903 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
4907 // fetch the lighting from the worldmodel data
4908 VectorClear(ent->modellight_ambient);
4909 VectorClear(ent->modellight_diffuse);
4910 VectorClear(tempdiffusenormal);
4911 if (ent->flags & RENDER_LIGHT)
4914 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4916 // complete lightning for lit sprites
4917 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4918 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4920 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4921 org[2] = org[2] + r_overheadsprites_pushback.value;
4922 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4925 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4927 if(ent->flags & RENDER_EQUALIZE)
4929 // first fix up ambient lighting...
4930 if(r_equalize_entities_minambient.value > 0)
4932 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4935 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4936 if(fa < r_equalize_entities_minambient.value * fd)
4939 // fa'/fd' = minambient
4940 // fa'+0.25*fd' = fa+0.25*fd
4942 // fa' = fd' * minambient
4943 // fd'*(0.25+minambient) = fa+0.25*fd
4945 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4946 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4948 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4949 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
4950 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4951 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4956 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4958 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4959 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4963 // adjust brightness and saturation to target
4964 avg[0] = avg[1] = avg[2] = fa / f;
4965 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4966 avg[0] = avg[1] = avg[2] = fd / f;
4967 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4973 VectorSet(ent->modellight_ambient, 1, 1, 1);
4976 // move the light direction into modelspace coordinates for lighting code
4977 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4978 if(VectorLength2(ent->modellight_lightdir) == 0)
4979 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4980 VectorNormalize(ent->modellight_lightdir);
4984 #define MAX_LINEOFSIGHTTRACES 64
4986 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4989 vec3_t boxmins, boxmaxs;
4992 dp_model_t *model = r_refdef.scene.worldmodel;
4994 if (!model || !model->brush.TraceLineOfSight)
4997 // expand the box a little
4998 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4999 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5000 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5001 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5002 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5003 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5005 // return true if eye is inside enlarged box
5006 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5010 VectorCopy(eye, start);
5011 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5012 if (model->brush.TraceLineOfSight(model, start, end))
5015 // try various random positions
5016 for (i = 0;i < numsamples;i++)
5018 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5019 if (model->brush.TraceLineOfSight(model, start, end))
5027 static void R_View_UpdateEntityVisible (void)
5032 entity_render_t *ent;
5034 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5035 : r_fb.water.hideplayer ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5036 : (chase_active.integer || r_fb.water.renderingscene) ? RENDER_VIEWMODEL
5037 : RENDER_EXTERIORMODEL;
5038 if (!r_drawviewmodel.integer)
5039 renderimask |= RENDER_VIEWMODEL;
5040 if (!r_drawexteriormodel.integer)
5041 renderimask |= RENDER_EXTERIORMODEL;
5042 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5044 // worldmodel can check visibility
5045 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5046 for (i = 0;i < r_refdef.scene.numentities;i++)
5048 ent = r_refdef.scene.entities[i];
5049 if (!(ent->flags & renderimask))
5050 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)))
5051 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))
5052 r_refdef.viewcache.entityvisible[i] = true;
5057 // no worldmodel or it can't check visibility
5058 for (i = 0;i < r_refdef.scene.numentities;i++)
5060 ent = r_refdef.scene.entities[i];
5061 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));
5064 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5065 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5067 for (i = 0;i < r_refdef.scene.numentities;i++)
5069 if (!r_refdef.viewcache.entityvisible[i])
5071 ent = r_refdef.scene.entities[i];
5072 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5074 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5076 continue; // temp entities do pvs only
5077 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5078 ent->last_trace_visibility = realtime;
5079 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5080 r_refdef.viewcache.entityvisible[i] = 0;
5086 /// only used if skyrendermasked, and normally returns false
5087 static int R_DrawBrushModelsSky (void)
5090 entity_render_t *ent;
5093 for (i = 0;i < r_refdef.scene.numentities;i++)
5095 if (!r_refdef.viewcache.entityvisible[i])
5097 ent = r_refdef.scene.entities[i];
5098 if (!ent->model || !ent->model->DrawSky)
5100 ent->model->DrawSky(ent);
5106 static void R_DrawNoModel(entity_render_t *ent);
5107 static void R_DrawModels(void)
5110 entity_render_t *ent;
5112 for (i = 0;i < r_refdef.scene.numentities;i++)
5114 if (!r_refdef.viewcache.entityvisible[i])
5116 ent = r_refdef.scene.entities[i];
5117 r_refdef.stats.entities++;
5119 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5122 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5123 Con_Printf("R_DrawModels\n");
5124 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]);
5125 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);
5126 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);
5129 if (ent->model && ent->model->Draw != NULL)
5130 ent->model->Draw(ent);
5136 static void R_DrawModelsDepth(void)
5139 entity_render_t *ent;
5141 for (i = 0;i < r_refdef.scene.numentities;i++)
5143 if (!r_refdef.viewcache.entityvisible[i])
5145 ent = r_refdef.scene.entities[i];
5146 if (ent->model && ent->model->DrawDepth != NULL)
5147 ent->model->DrawDepth(ent);
5151 static void R_DrawModelsDebug(void)
5154 entity_render_t *ent;
5156 for (i = 0;i < r_refdef.scene.numentities;i++)
5158 if (!r_refdef.viewcache.entityvisible[i])
5160 ent = r_refdef.scene.entities[i];
5161 if (ent->model && ent->model->DrawDebug != NULL)
5162 ent->model->DrawDebug(ent);
5166 static void R_DrawModelsAddWaterPlanes(void)
5169 entity_render_t *ent;
5171 for (i = 0;i < r_refdef.scene.numentities;i++)
5173 if (!r_refdef.viewcache.entityvisible[i])
5175 ent = r_refdef.scene.entities[i];
5176 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5177 ent->model->DrawAddWaterPlanes(ent);
5181 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}};
5183 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5185 if (r_hdr_irisadaptation.integer)
5190 vec3_t diffusenormal;
5192 vec_t brightness = 0.0f;
5197 VectorCopy(r_refdef.view.forward, forward);
5198 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5200 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5201 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5202 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5203 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5204 d = DotProduct(forward, diffusenormal);
5205 brightness += VectorLength(ambient);
5207 brightness += d * VectorLength(diffuse);
5209 brightness *= 1.0f / c;
5210 brightness += 0.00001f; // make sure it's never zero
5211 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5212 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5213 current = r_hdr_irisadaptation_value.value;
5215 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5216 else if (current > goal)
5217 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5218 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5219 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5221 else if (r_hdr_irisadaptation_value.value != 1.0f)
5222 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5225 static void R_View_SetFrustum(const int *scissor)
5228 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5229 vec3_t forward, left, up, origin, v;
5233 // flipped x coordinates (because x points left here)
5234 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5235 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5237 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5238 switch(vid.renderpath)
5240 case RENDERPATH_D3D9:
5241 case RENDERPATH_D3D10:
5242 case RENDERPATH_D3D11:
5243 // non-flipped y coordinates
5244 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5245 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5247 case RENDERPATH_SOFT:
5248 case RENDERPATH_GL11:
5249 case RENDERPATH_GL13:
5250 case RENDERPATH_GL20:
5251 case RENDERPATH_GLES1:
5252 case RENDERPATH_GLES2:
5253 // non-flipped y coordinates
5254 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5255 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5260 // we can't trust r_refdef.view.forward and friends in reflected scenes
5261 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5264 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5265 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5266 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5267 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5268 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5269 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5270 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5271 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5272 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5273 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5274 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5275 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5279 zNear = r_refdef.nearclip;
5280 nudge = 1.0 - 1.0 / (1<<23);
5281 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5282 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5283 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5284 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5285 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5286 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5287 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5288 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5294 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5295 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5296 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5297 r_refdef.view.frustum[0].dist = m[15] - m[12];
5299 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5300 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5301 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5302 r_refdef.view.frustum[1].dist = m[15] + m[12];
5304 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5305 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5306 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5307 r_refdef.view.frustum[2].dist = m[15] - m[13];
5309 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5310 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5311 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5312 r_refdef.view.frustum[3].dist = m[15] + m[13];
5314 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5315 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5316 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5317 r_refdef.view.frustum[4].dist = m[15] - m[14];
5319 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5320 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5321 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5322 r_refdef.view.frustum[5].dist = m[15] + m[14];
5325 if (r_refdef.view.useperspective)
5327 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5328 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]);
5329 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]);
5330 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]);
5331 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]);
5333 // then the normals from the corners relative to origin
5334 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5335 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5336 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5337 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5339 // in a NORMAL view, forward cross left == up
5340 // in a REFLECTED view, forward cross left == down
5341 // so our cross products above need to be adjusted for a left handed coordinate system
5342 CrossProduct(forward, left, v);
5343 if(DotProduct(v, up) < 0)
5345 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5346 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5347 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5348 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5351 // Leaving those out was a mistake, those were in the old code, and they
5352 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5353 // I couldn't reproduce it after adding those normalizations. --blub
5354 VectorNormalize(r_refdef.view.frustum[0].normal);
5355 VectorNormalize(r_refdef.view.frustum[1].normal);
5356 VectorNormalize(r_refdef.view.frustum[2].normal);
5357 VectorNormalize(r_refdef.view.frustum[3].normal);
5359 // make the corners absolute
5360 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5361 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5362 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5363 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5366 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5368 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5369 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5370 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5371 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5372 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5376 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5377 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5378 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5379 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5380 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5381 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5382 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5383 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5384 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5385 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5387 r_refdef.view.numfrustumplanes = 5;
5389 if (r_refdef.view.useclipplane)
5391 r_refdef.view.numfrustumplanes = 6;
5392 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5395 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5396 PlaneClassify(r_refdef.view.frustum + i);
5398 // LordHavoc: note to all quake engine coders, Quake had a special case
5399 // for 90 degrees which assumed a square view (wrong), so I removed it,
5400 // Quake2 has it disabled as well.
5402 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5403 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5404 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5405 //PlaneClassify(&frustum[0]);
5407 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5408 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5409 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5410 //PlaneClassify(&frustum[1]);
5412 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5413 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5414 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5415 //PlaneClassify(&frustum[2]);
5417 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5418 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5419 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5420 //PlaneClassify(&frustum[3]);
5423 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5424 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5425 //PlaneClassify(&frustum[4]);
5428 static void R_View_UpdateWithScissor(const int *myscissor)
5430 R_Main_ResizeViewCache();
5431 R_View_SetFrustum(myscissor);
5432 R_View_WorldVisibility(r_refdef.view.useclipplane);
5433 R_View_UpdateEntityVisible();
5434 R_View_UpdateEntityLighting();
5437 static void R_View_Update(void)
5439 R_Main_ResizeViewCache();
5440 R_View_SetFrustum(NULL);
5441 R_View_WorldVisibility(r_refdef.view.useclipplane);
5442 R_View_UpdateEntityVisible();
5443 R_View_UpdateEntityLighting();
5446 float viewscalefpsadjusted = 1.0f;
5448 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5450 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5451 scale = bound(0.03125f, scale, 1.0f);
5452 *outwidth = (int)ceil(width * scale);
5453 *outheight = (int)ceil(height * scale);
5456 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5458 const float *customclipplane = NULL;
5460 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5461 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5463 // LordHavoc: couldn't figure out how to make this approach the
5464 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5465 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5466 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5467 dist = r_refdef.view.clipplane.dist;
5468 plane[0] = r_refdef.view.clipplane.normal[0];
5469 plane[1] = r_refdef.view.clipplane.normal[1];
5470 plane[2] = r_refdef.view.clipplane.normal[2];
5472 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5475 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5476 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5478 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5479 if (!r_refdef.view.useperspective)
5480 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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);
5481 else if (vid.stencil && r_useinfinitefarclip.integer)
5482 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5484 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5485 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5486 R_SetViewport(&r_refdef.view.viewport);
5487 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5489 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5490 float screenplane[4];
5491 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5492 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5493 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5494 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5495 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5499 void R_EntityMatrix(const matrix4x4_t *matrix)
5501 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5503 gl_modelmatrixchanged = false;
5504 gl_modelmatrix = *matrix;
5505 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5506 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5507 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5508 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5510 switch(vid.renderpath)
5512 case RENDERPATH_D3D9:
5514 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5515 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5518 case RENDERPATH_D3D10:
5519 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5521 case RENDERPATH_D3D11:
5522 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5524 case RENDERPATH_GL11:
5525 case RENDERPATH_GL13:
5526 case RENDERPATH_GLES1:
5527 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5529 case RENDERPATH_SOFT:
5530 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5531 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5533 case RENDERPATH_GL20:
5534 case RENDERPATH_GLES2:
5535 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5536 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5542 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5544 r_viewport_t viewport;
5548 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5549 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, x2, y2, -10, 100, NULL);
5550 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5551 R_SetViewport(&viewport);
5552 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5553 GL_Color(1, 1, 1, 1);
5554 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5555 GL_BlendFunc(GL_ONE, GL_ZERO);
5556 GL_ScissorTest(false);
5557 GL_DepthMask(false);
5558 GL_DepthRange(0, 1);
5559 GL_DepthTest(false);
5560 GL_DepthFunc(GL_LEQUAL);
5561 R_EntityMatrix(&identitymatrix);
5562 R_Mesh_ResetTextureState();
5563 GL_PolygonOffset(0, 0);
5564 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5565 switch(vid.renderpath)
5567 case RENDERPATH_GL11:
5568 case RENDERPATH_GL13:
5569 case RENDERPATH_GL20:
5570 case RENDERPATH_GLES1:
5571 case RENDERPATH_GLES2:
5572 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5574 case RENDERPATH_D3D9:
5575 case RENDERPATH_D3D10:
5576 case RENDERPATH_D3D11:
5577 case RENDERPATH_SOFT:
5580 GL_CullFace(GL_NONE);
5585 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5589 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5592 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5596 R_SetupView(true, fbo, depthtexture, colortexture);
5597 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5598 GL_Color(1, 1, 1, 1);
5599 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5600 GL_BlendFunc(GL_ONE, GL_ZERO);
5601 GL_ScissorTest(true);
5603 GL_DepthRange(0, 1);
5605 GL_DepthFunc(GL_LEQUAL);
5606 R_EntityMatrix(&identitymatrix);
5607 R_Mesh_ResetTextureState();
5608 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5609 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5610 switch(vid.renderpath)
5612 case RENDERPATH_GL11:
5613 case RENDERPATH_GL13:
5614 case RENDERPATH_GL20:
5615 case RENDERPATH_GLES1:
5616 case RENDERPATH_GLES2:
5617 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5619 case RENDERPATH_D3D9:
5620 case RENDERPATH_D3D10:
5621 case RENDERPATH_D3D11:
5622 case RENDERPATH_SOFT:
5625 GL_CullFace(r_refdef.view.cullface_back);
5630 R_RenderView_UpdateViewVectors
5633 void R_RenderView_UpdateViewVectors(void)
5635 // break apart the view matrix into vectors for various purposes
5636 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5637 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5638 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5639 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5640 // make an inverted copy of the view matrix for tracking sprites
5641 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5644 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5645 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5647 static void R_Water_StartFrame(void)
5650 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5651 r_waterstate_waterplane_t *p;
5652 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5654 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5657 switch(vid.renderpath)
5659 case RENDERPATH_GL20:
5660 case RENDERPATH_D3D9:
5661 case RENDERPATH_D3D10:
5662 case RENDERPATH_D3D11:
5663 case RENDERPATH_SOFT:
5664 case RENDERPATH_GLES2:
5666 case RENDERPATH_GL11:
5667 case RENDERPATH_GL13:
5668 case RENDERPATH_GLES1:
5672 // set waterwidth and waterheight to the water resolution that will be
5673 // used (often less than the screen resolution for faster rendering)
5674 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5676 // calculate desired texture sizes
5677 // can't use water if the card does not support the texture size
5678 if (!r_water.integer || r_showsurfaces.integer)
5679 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5680 else if (vid.support.arb_texture_non_power_of_two)
5682 texturewidth = waterwidth;
5683 textureheight = waterheight;
5684 camerawidth = waterwidth;
5685 cameraheight = waterheight;
5689 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5690 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5691 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5692 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5695 // allocate textures as needed
5696 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5698 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5699 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5701 if (p->texture_refraction)
5702 R_FreeTexture(p->texture_refraction);
5703 p->texture_refraction = NULL;
5704 if (p->fbo_refraction)
5705 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5706 p->fbo_refraction = 0;
5707 if (p->texture_reflection)
5708 R_FreeTexture(p->texture_reflection);
5709 p->texture_reflection = NULL;
5710 if (p->fbo_reflection)
5711 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5712 p->fbo_reflection = 0;
5713 if (p->texture_camera)
5714 R_FreeTexture(p->texture_camera);
5715 p->texture_camera = NULL;
5717 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5720 memset(&r_fb.water, 0, sizeof(r_fb.water));
5721 r_fb.water.texturewidth = texturewidth;
5722 r_fb.water.textureheight = textureheight;
5723 r_fb.water.camerawidth = camerawidth;
5724 r_fb.water.cameraheight = cameraheight;
5727 if (r_fb.water.texturewidth)
5729 int scaledwidth, scaledheight;
5731 r_fb.water.enabled = true;
5733 // water resolution is usually reduced
5734 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5735 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5736 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5738 // set up variables that will be used in shader setup
5739 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5740 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5741 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5742 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5745 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5746 r_fb.water.numwaterplanes = 0;
5749 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5751 int planeindex, bestplaneindex, vertexindex;
5752 vec3_t mins, maxs, normal, center, v, n;
5753 vec_t planescore, bestplanescore;
5755 r_waterstate_waterplane_t *p;
5756 texture_t *t = R_GetCurrentTexture(surface->texture);
5758 rsurface.texture = t;
5759 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5760 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5761 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5763 // average the vertex normals, find the surface bounds (after deformvertexes)
5764 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5765 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5766 VectorCopy(n, normal);
5767 VectorCopy(v, mins);
5768 VectorCopy(v, maxs);
5769 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5771 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5772 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5773 VectorAdd(normal, n, normal);
5774 mins[0] = min(mins[0], v[0]);
5775 mins[1] = min(mins[1], v[1]);
5776 mins[2] = min(mins[2], v[2]);
5777 maxs[0] = max(maxs[0], v[0]);
5778 maxs[1] = max(maxs[1], v[1]);
5779 maxs[2] = max(maxs[2], v[2]);
5781 VectorNormalize(normal);
5782 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5784 VectorCopy(normal, plane.normal);
5785 VectorNormalize(plane.normal);
5786 plane.dist = DotProduct(center, plane.normal);
5787 PlaneClassify(&plane);
5788 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5790 // skip backfaces (except if nocullface is set)
5791 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5793 VectorNegate(plane.normal, plane.normal);
5795 PlaneClassify(&plane);
5799 // find a matching plane if there is one
5800 bestplaneindex = -1;
5801 bestplanescore = 1048576.0f;
5802 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5804 if(p->camera_entity == t->camera_entity)
5806 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5807 if (bestplaneindex < 0 || bestplanescore > planescore)
5809 bestplaneindex = planeindex;
5810 bestplanescore = planescore;
5814 planeindex = bestplaneindex;
5815 p = r_fb.water.waterplanes + planeindex;
5817 // if this surface does not fit any known plane rendered this frame, add one
5818 if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5820 // store the new plane
5821 planeindex = r_fb.water.numwaterplanes++;
5822 p = r_fb.water.waterplanes + planeindex;
5824 // clear materialflags and pvs
5825 p->materialflags = 0;
5826 p->pvsvalid = false;
5827 p->camera_entity = t->camera_entity;
5828 VectorCopy(mins, p->mins);
5829 VectorCopy(maxs, p->maxs);
5833 // merge mins/maxs when we're adding this surface to the plane
5834 p->mins[0] = min(p->mins[0], mins[0]);
5835 p->mins[1] = min(p->mins[1], mins[1]);
5836 p->mins[2] = min(p->mins[2], mins[2]);
5837 p->maxs[0] = max(p->maxs[0], maxs[0]);
5838 p->maxs[1] = max(p->maxs[1], maxs[1]);
5839 p->maxs[2] = max(p->maxs[2], maxs[2]);
5841 // merge this surface's materialflags into the waterplane
5842 p->materialflags |= t->currentmaterialflags;
5843 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5845 // merge this surface's PVS into the waterplane
5846 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5847 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5849 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5855 extern cvar_t r_drawparticles;
5856 extern cvar_t r_drawdecals;
5858 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5861 r_refdef_view_t originalview;
5862 r_refdef_view_t myview;
5863 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;
5864 r_waterstate_waterplane_t *p;
5866 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5869 originalview = r_refdef.view;
5871 // lowquality hack, temporarily shut down some cvars and restore afterwards
5872 qualityreduction = r_water_lowquality.integer;
5873 if (qualityreduction > 0)
5875 if (qualityreduction >= 1)
5877 old_r_shadows = r_shadows.integer;
5878 old_r_worldrtlight = r_shadow_realtime_world.integer;
5879 old_r_dlight = r_shadow_realtime_dlight.integer;
5880 Cvar_SetValueQuick(&r_shadows, 0);
5881 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5882 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5884 if (qualityreduction >= 2)
5886 old_r_dynamic = r_dynamic.integer;
5887 old_r_particles = r_drawparticles.integer;
5888 old_r_decals = r_drawdecals.integer;
5889 Cvar_SetValueQuick(&r_dynamic, 0);
5890 Cvar_SetValueQuick(&r_drawparticles, 0);
5891 Cvar_SetValueQuick(&r_drawdecals, 0);
5895 // make sure enough textures are allocated
5896 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5898 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5900 if (!p->texture_refraction)
5901 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5902 if (!p->texture_refraction)
5906 if (r_fb.water.depthtexture == NULL)
5907 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5908 if (p->fbo_refraction == 0)
5909 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5912 else if (p->materialflags & MATERIALFLAG_CAMERA)
5914 if (!p->texture_camera)
5915 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5916 if (!p->texture_camera)
5920 if (r_fb.water.depthtexture == NULL)
5921 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5922 if (p->fbo_camera == 0)
5923 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5927 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5929 if (!p->texture_reflection)
5930 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5931 if (!p->texture_reflection)
5935 if (r_fb.water.depthtexture == NULL)
5936 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5937 if (p->fbo_reflection == 0)
5938 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5944 r_refdef.view = originalview;
5945 r_refdef.view.showdebug = false;
5946 r_refdef.view.width = r_fb.water.waterwidth;
5947 r_refdef.view.height = r_fb.water.waterheight;
5948 r_refdef.view.useclipplane = true;
5949 myview = r_refdef.view;
5950 r_fb.water.renderingscene = true;
5951 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5953 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5955 r_refdef.view = myview;
5956 if(r_water_scissormode.integer)
5958 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5959 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5960 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5963 // render reflected scene and copy into texture
5964 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5965 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5966 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5967 r_refdef.view.clipplane = p->plane;
5968 // reverse the cullface settings for this render
5969 r_refdef.view.cullface_front = GL_FRONT;
5970 r_refdef.view.cullface_back = GL_BACK;
5971 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5973 r_refdef.view.usecustompvs = true;
5975 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5977 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5980 r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5981 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5982 R_ClearScreen(r_refdef.fogenabled);
5983 if(r_water_scissormode.integer & 2)
5984 R_View_UpdateWithScissor(myscissor);
5987 R_AnimCache_CacheVisibleEntities();
5988 if(r_water_scissormode.integer & 1)
5989 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5990 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5992 if (!p->fbo_reflection)
5993 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);
5994 r_fb.water.hideplayer = false;
5997 // render the normal view scene and copy into texture
5998 // (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)
5999 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6001 r_refdef.view = myview;
6002 if(r_water_scissormode.integer)
6004 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6005 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6006 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6009 r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6011 r_refdef.view.clipplane = p->plane;
6012 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6013 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6015 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6017 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6018 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6019 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6020 R_RenderView_UpdateViewVectors();
6021 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6023 r_refdef.view.usecustompvs = true;
6024 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);
6028 PlaneClassify(&r_refdef.view.clipplane);
6030 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6031 R_ClearScreen(r_refdef.fogenabled);
6032 if(r_water_scissormode.integer & 2)
6033 R_View_UpdateWithScissor(myscissor);
6036 R_AnimCache_CacheVisibleEntities();
6037 if(r_water_scissormode.integer & 1)
6038 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6039 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6041 if (!p->fbo_refraction)
6042 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);
6043 r_fb.water.hideplayer = false;
6045 else if (p->materialflags & MATERIALFLAG_CAMERA)
6047 r_refdef.view = myview;
6049 r_refdef.view.clipplane = p->plane;
6050 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6051 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6053 r_refdef.view.width = r_fb.water.camerawidth;
6054 r_refdef.view.height = r_fb.water.cameraheight;
6055 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6056 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6057 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6058 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6060 if(p->camera_entity)
6062 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6063 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6066 // note: all of the view is used for displaying... so
6067 // there is no use in scissoring
6069 // reverse the cullface settings for this render
6070 r_refdef.view.cullface_front = GL_FRONT;
6071 r_refdef.view.cullface_back = GL_BACK;
6072 // also reverse the view matrix
6073 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
6074 R_RenderView_UpdateViewVectors();
6075 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6077 r_refdef.view.usecustompvs = true;
6078 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);
6081 // camera needs no clipplane
6082 r_refdef.view.useclipplane = false;
6084 PlaneClassify(&r_refdef.view.clipplane);
6086 r_fb.water.hideplayer = false;
6088 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6089 R_ClearScreen(r_refdef.fogenabled);
6091 R_AnimCache_CacheVisibleEntities();
6092 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6095 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);
6096 r_fb.water.hideplayer = false;
6100 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6101 r_fb.water.renderingscene = false;
6102 r_refdef.view = originalview;
6103 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6104 if (!r_fb.water.depthtexture)
6105 R_ClearScreen(r_refdef.fogenabled);
6107 R_AnimCache_CacheVisibleEntities();
6110 r_refdef.view = originalview;
6111 r_fb.water.renderingscene = false;
6112 Cvar_SetValueQuick(&r_water, 0);
6113 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6115 // lowquality hack, restore cvars
6116 if (qualityreduction > 0)
6118 if (qualityreduction >= 1)
6120 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6121 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6122 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6124 if (qualityreduction >= 2)
6126 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6127 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6128 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6133 static void R_Bloom_StartFrame(void)
6136 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6137 int viewwidth, viewheight;
6138 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6139 textype_t textype = TEXTYPE_COLORBUFFER;
6141 switch (vid.renderpath)
6143 case RENDERPATH_GL20:
6144 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6145 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6147 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6148 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6151 case RENDERPATH_GL11:
6152 case RENDERPATH_GL13:
6153 case RENDERPATH_GLES1:
6154 case RENDERPATH_GLES2:
6155 case RENDERPATH_D3D9:
6156 case RENDERPATH_D3D10:
6157 case RENDERPATH_D3D11:
6158 r_fb.usedepthtextures = false;
6160 case RENDERPATH_SOFT:
6161 r_fb.usedepthtextures = true;
6165 if (r_viewscale_fpsscaling.integer)
6167 double actualframetime;
6168 double targetframetime;
6170 actualframetime = r_refdef.lastdrawscreentime;
6171 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6172 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6173 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6174 if (r_viewscale_fpsscaling_stepsize.value > 0)
6175 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6176 viewscalefpsadjusted += adjust;
6177 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6180 viewscalefpsadjusted = 1.0f;
6182 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6184 switch(vid.renderpath)
6186 case RENDERPATH_GL20:
6187 case RENDERPATH_D3D9:
6188 case RENDERPATH_D3D10:
6189 case RENDERPATH_D3D11:
6190 case RENDERPATH_SOFT:
6191 case RENDERPATH_GLES2:
6193 case RENDERPATH_GL11:
6194 case RENDERPATH_GL13:
6195 case RENDERPATH_GLES1:
6199 // set bloomwidth and bloomheight to the bloom resolution that will be
6200 // used (often less than the screen resolution for faster rendering)
6201 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6202 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6203 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6204 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6205 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6207 // calculate desired texture sizes
6208 if (vid.support.arb_texture_non_power_of_two)
6210 screentexturewidth = vid.width;
6211 screentextureheight = vid.height;
6212 bloomtexturewidth = r_fb.bloomwidth;
6213 bloomtextureheight = r_fb.bloomheight;
6217 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6218 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6219 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6220 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6223 if ((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))
6225 Cvar_SetValueQuick(&r_bloom, 0);
6226 Cvar_SetValueQuick(&r_motionblur, 0);
6227 Cvar_SetValueQuick(&r_damageblur, 0);
6230 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6232 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6234 && r_viewscale.value == 1.0f
6235 && !r_viewscale_fpsscaling.integer)
6236 screentexturewidth = screentextureheight = 0;
6237 if (!r_bloom.integer)
6238 bloomtexturewidth = bloomtextureheight = 0;
6240 // allocate textures as needed
6241 if (r_fb.screentexturewidth != screentexturewidth
6242 || r_fb.screentextureheight != screentextureheight
6243 || r_fb.bloomtexturewidth != bloomtexturewidth
6244 || r_fb.bloomtextureheight != bloomtextureheight
6245 || r_fb.textype != textype
6246 || useviewfbo != (r_fb.fbo != 0))
6248 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6250 if (r_fb.bloomtexture[i])
6251 R_FreeTexture(r_fb.bloomtexture[i]);
6252 r_fb.bloomtexture[i] = NULL;
6254 if (r_fb.bloomfbo[i])
6255 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6256 r_fb.bloomfbo[i] = 0;
6260 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6263 if (r_fb.colortexture)
6264 R_FreeTexture(r_fb.colortexture);
6265 r_fb.colortexture = NULL;
6267 if (r_fb.depthtexture)
6268 R_FreeTexture(r_fb.depthtexture);
6269 r_fb.depthtexture = NULL;
6271 if (r_fb.ghosttexture)
6272 R_FreeTexture(r_fb.ghosttexture);
6273 r_fb.ghosttexture = NULL;
6275 r_fb.screentexturewidth = screentexturewidth;
6276 r_fb.screentextureheight = screentextureheight;
6277 r_fb.bloomtexturewidth = bloomtexturewidth;
6278 r_fb.bloomtextureheight = bloomtextureheight;
6279 r_fb.textype = textype;
6281 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6283 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6284 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6285 r_fb.ghosttexture_valid = false;
6286 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6289 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6290 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6291 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6295 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6297 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6299 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6301 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6306 // bloom texture is a different resolution
6307 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6308 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6309 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6310 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6311 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6313 // set up a texcoord array for the full resolution screen image
6314 // (we have to keep this around to copy back during final render)
6315 r_fb.screentexcoord2f[0] = 0;
6316 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6317 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6318 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6319 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6320 r_fb.screentexcoord2f[5] = 0;
6321 r_fb.screentexcoord2f[6] = 0;
6322 r_fb.screentexcoord2f[7] = 0;
6326 for (i = 1;i < 8;i += 2)
6328 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6332 // set up a texcoord array for the reduced resolution bloom image
6333 // (which will be additive blended over the screen image)
6334 r_fb.bloomtexcoord2f[0] = 0;
6335 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6336 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6337 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6338 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6339 r_fb.bloomtexcoord2f[5] = 0;
6340 r_fb.bloomtexcoord2f[6] = 0;
6341 r_fb.bloomtexcoord2f[7] = 0;
6343 switch(vid.renderpath)
6345 case RENDERPATH_GL11:
6346 case RENDERPATH_GL13:
6347 case RENDERPATH_GL20:
6348 case RENDERPATH_SOFT:
6349 case RENDERPATH_GLES1:
6350 case RENDERPATH_GLES2:
6352 case RENDERPATH_D3D9:
6353 case RENDERPATH_D3D10:
6354 case RENDERPATH_D3D11:
6355 for (i = 0;i < 4;i++)
6357 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6358 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6359 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6360 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6365 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6368 r_refdef.view.clear = true;
6371 static void R_Bloom_MakeTexture(void)
6374 float xoffset, yoffset, r, brighten;
6376 float colorscale = r_bloom_colorscale.value;
6378 r_refdef.stats.bloom++;
6381 // this copy is unnecessary since it happens in R_BlendView already
6384 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6385 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6389 // scale down screen texture to the bloom texture size
6391 r_fb.bloomindex = 0;
6392 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6393 R_SetViewport(&r_fb.bloomviewport);
6394 GL_DepthTest(false);
6395 GL_BlendFunc(GL_ONE, GL_ZERO);
6396 GL_Color(colorscale, colorscale, colorscale, 1);
6397 // 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...
6398 switch(vid.renderpath)
6400 case RENDERPATH_GL11:
6401 case RENDERPATH_GL13:
6402 case RENDERPATH_GL20:
6403 case RENDERPATH_GLES1:
6404 case RENDERPATH_GLES2:
6405 case RENDERPATH_SOFT:
6406 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6408 case RENDERPATH_D3D9:
6409 case RENDERPATH_D3D10:
6410 case RENDERPATH_D3D11:
6411 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6414 // TODO: do boxfilter scale-down in shader?
6415 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6416 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6417 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6419 // we now have a properly scaled bloom image
6420 if (!r_fb.bloomfbo[r_fb.bloomindex])
6422 // copy it into the bloom texture
6423 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6424 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6427 // multiply bloom image by itself as many times as desired
6428 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6430 intex = r_fb.bloomtexture[r_fb.bloomindex];
6431 r_fb.bloomindex ^= 1;
6432 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6434 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6435 if (!r_fb.bloomfbo[r_fb.bloomindex])
6437 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6438 GL_Color(r,r,r,1); // apply fix factor
6443 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6444 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6445 GL_Color(1,1,1,1); // no fix factor supported here
6447 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6448 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6449 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6450 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6452 if (!r_fb.bloomfbo[r_fb.bloomindex])
6454 // copy the darkened image to a texture
6455 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6456 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6460 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6461 brighten = r_bloom_brighten.value;
6462 brighten = sqrt(brighten);
6464 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6466 for (dir = 0;dir < 2;dir++)
6468 intex = r_fb.bloomtexture[r_fb.bloomindex];
6469 r_fb.bloomindex ^= 1;
6470 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6471 // blend on at multiple vertical offsets to achieve a vertical blur
6472 // TODO: do offset blends using GLSL
6473 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6474 GL_BlendFunc(GL_ONE, GL_ZERO);
6475 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6476 for (x = -range;x <= range;x++)
6478 if (!dir){xoffset = 0;yoffset = x;}
6479 else {xoffset = x;yoffset = 0;}
6480 xoffset /= (float)r_fb.bloomtexturewidth;
6481 yoffset /= (float)r_fb.bloomtextureheight;
6482 // compute a texcoord array with the specified x and y offset
6483 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6484 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6485 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6486 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6487 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6488 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6489 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6490 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6491 // this r value looks like a 'dot' particle, fading sharply to
6492 // black at the edges
6493 // (probably not realistic but looks good enough)
6494 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6495 //r = brighten/(range*2+1);
6496 r = brighten / (range * 2 + 1);
6498 r *= (1 - x*x/(float)(range*range));
6499 GL_Color(r, r, r, 1);
6500 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6501 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6502 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6503 GL_BlendFunc(GL_ONE, GL_ONE);
6506 if (!r_fb.bloomfbo[r_fb.bloomindex])
6508 // copy the vertically or horizontally blurred bloom view to a texture
6509 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6510 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6515 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6517 unsigned int permutation;
6518 float uservecs[4][4];
6520 R_EntityMatrix(&identitymatrix);
6522 switch (vid.renderpath)
6524 case RENDERPATH_GL20:
6525 case RENDERPATH_D3D9:
6526 case RENDERPATH_D3D10:
6527 case RENDERPATH_D3D11:
6528 case RENDERPATH_SOFT:
6529 case RENDERPATH_GLES2:
6531 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6532 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6533 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6534 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6535 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6537 if (r_fb.colortexture)
6541 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6542 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6545 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6547 // declare variables
6548 float blur_factor, blur_mouseaccel, blur_velocity;
6549 static float blur_average;
6550 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6552 // set a goal for the factoring
6553 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6554 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6555 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6556 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6557 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6558 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6560 // from the goal, pick an averaged value between goal and last value
6561 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6562 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6564 // enforce minimum amount of blur
6565 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6567 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6569 // calculate values into a standard alpha
6570 cl.motionbluralpha = 1 - exp(-
6572 (r_motionblur.value * blur_factor / 80)
6574 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6577 max(0.0001, cl.time - cl.oldtime) // fps independent
6580 // randomization for the blur value to combat persistent ghosting
6581 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6582 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6585 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6586 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6588 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6589 GL_Color(1, 1, 1, cl.motionbluralpha);
6590 switch(vid.renderpath)
6592 case RENDERPATH_GL11:
6593 case RENDERPATH_GL13:
6594 case RENDERPATH_GL20:
6595 case RENDERPATH_GLES1:
6596 case RENDERPATH_GLES2:
6597 case RENDERPATH_SOFT:
6598 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6600 case RENDERPATH_D3D9:
6601 case RENDERPATH_D3D10:
6602 case RENDERPATH_D3D11:
6603 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6606 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6607 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6608 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6611 // updates old view angles for next pass
6612 VectorCopy(cl.viewangles, blur_oldangles);
6614 // copy view into the ghost texture
6615 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6616 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6617 r_fb.ghosttexture_valid = true;
6622 // no r_fb.colortexture means we're rendering to the real fb
6623 // we may still have to do view tint...
6624 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6626 // apply a color tint to the whole view
6627 R_ResetViewRendering2D(0, NULL, NULL);
6628 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6629 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6630 R_SetupShader_Generic_NoTexture(false, true);
6631 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6632 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6634 break; // no screen processing, no bloom, skip it
6637 if (r_fb.bloomtexture[0])
6639 // make the bloom texture
6640 R_Bloom_MakeTexture();
6643 #if _MSC_VER >= 1400
6644 #define sscanf sscanf_s
6646 memset(uservecs, 0, sizeof(uservecs));
6647 if (r_glsl_postprocess_uservec1_enable.integer)
6648 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6649 if (r_glsl_postprocess_uservec2_enable.integer)
6650 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6651 if (r_glsl_postprocess_uservec3_enable.integer)
6652 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6653 if (r_glsl_postprocess_uservec4_enable.integer)
6654 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6656 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6657 GL_Color(1, 1, 1, 1);
6658 GL_BlendFunc(GL_ONE, GL_ZERO);
6660 switch(vid.renderpath)
6662 case RENDERPATH_GL20:
6663 case RENDERPATH_GLES2:
6664 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6665 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6666 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6667 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6668 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6669 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]);
6670 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6671 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]);
6672 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]);
6673 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]);
6674 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]);
6675 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6676 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6677 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);
6679 case RENDERPATH_D3D9:
6681 // 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...
6682 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6683 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6684 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6685 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6686 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6687 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6688 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6689 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6690 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6691 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6692 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6693 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6694 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6695 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6698 case RENDERPATH_D3D10:
6699 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6701 case RENDERPATH_D3D11:
6702 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6704 case RENDERPATH_SOFT:
6705 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6706 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6707 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6708 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6709 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6710 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6711 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6712 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6713 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6714 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6715 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6716 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6717 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6718 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6723 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6724 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6726 case RENDERPATH_GL11:
6727 case RENDERPATH_GL13:
6728 case RENDERPATH_GLES1:
6729 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6731 // apply a color tint to the whole view
6732 R_ResetViewRendering2D(0, NULL, NULL);
6733 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6734 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6735 R_SetupShader_Generic_NoTexture(false, true);
6736 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6737 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6743 matrix4x4_t r_waterscrollmatrix;
6745 void R_UpdateFog(void)
6748 if (gamemode == GAME_NEHAHRA)
6750 if (gl_fogenable.integer)
6752 r_refdef.oldgl_fogenable = true;
6753 r_refdef.fog_density = gl_fogdensity.value;
6754 r_refdef.fog_red = gl_fogred.value;
6755 r_refdef.fog_green = gl_foggreen.value;
6756 r_refdef.fog_blue = gl_fogblue.value;
6757 r_refdef.fog_alpha = 1;
6758 r_refdef.fog_start = 0;
6759 r_refdef.fog_end = gl_skyclip.value;
6760 r_refdef.fog_height = 1<<30;
6761 r_refdef.fog_fadedepth = 128;
6763 else if (r_refdef.oldgl_fogenable)
6765 r_refdef.oldgl_fogenable = false;
6766 r_refdef.fog_density = 0;
6767 r_refdef.fog_red = 0;
6768 r_refdef.fog_green = 0;
6769 r_refdef.fog_blue = 0;
6770 r_refdef.fog_alpha = 0;
6771 r_refdef.fog_start = 0;
6772 r_refdef.fog_end = 0;
6773 r_refdef.fog_height = 1<<30;
6774 r_refdef.fog_fadedepth = 128;
6779 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6780 r_refdef.fog_start = max(0, r_refdef.fog_start);
6781 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6783 if (r_refdef.fog_density && r_drawfog.integer)
6785 r_refdef.fogenabled = true;
6786 // this is the point where the fog reaches 0.9986 alpha, which we
6787 // consider a good enough cutoff point for the texture
6788 // (0.9986 * 256 == 255.6)
6789 if (r_fog_exp2.integer)
6790 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6792 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6793 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6794 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6795 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6796 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6797 R_BuildFogHeightTexture();
6798 // fog color was already set
6799 // update the fog texture
6800 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)
6801 R_BuildFogTexture();
6802 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6803 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6806 r_refdef.fogenabled = false;
6809 if (r_refdef.fog_density)
6811 r_refdef.fogcolor[0] = r_refdef.fog_red;
6812 r_refdef.fogcolor[1] = r_refdef.fog_green;
6813 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6815 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6816 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6817 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6818 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6822 VectorCopy(r_refdef.fogcolor, fogvec);
6823 // color.rgb *= ContrastBoost * SceneBrightness;
6824 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6825 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6826 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6827 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6832 void R_UpdateVariables(void)
6836 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6838 r_refdef.farclip = r_farclip_base.value;
6839 if (r_refdef.scene.worldmodel)
6840 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6841 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6843 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6844 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6845 r_refdef.polygonfactor = 0;
6846 r_refdef.polygonoffset = 0;
6847 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6848 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6850 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6851 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6852 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6853 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6854 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6855 if (FAKELIGHT_ENABLED)
6857 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6859 else if (r_refdef.scene.worldmodel)
6861 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6863 if (r_showsurfaces.integer)
6865 r_refdef.scene.rtworld = false;
6866 r_refdef.scene.rtworldshadows = false;
6867 r_refdef.scene.rtdlight = false;
6868 r_refdef.scene.rtdlightshadows = false;
6869 r_refdef.lightmapintensity = 0;
6872 switch(vid.renderpath)
6874 case RENDERPATH_GL20:
6875 case RENDERPATH_D3D9:
6876 case RENDERPATH_D3D10:
6877 case RENDERPATH_D3D11:
6878 case RENDERPATH_SOFT:
6879 case RENDERPATH_GLES2:
6880 if(v_glslgamma.integer && !vid_gammatables_trivial)
6882 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6884 // build GLSL gamma texture
6885 #define RAMPWIDTH 256
6886 unsigned short ramp[RAMPWIDTH * 3];
6887 unsigned char rampbgr[RAMPWIDTH][4];
6890 r_texture_gammaramps_serial = vid_gammatables_serial;
6892 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6893 for(i = 0; i < RAMPWIDTH; ++i)
6895 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6896 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6897 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6900 if (r_texture_gammaramps)
6902 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6906 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6912 // remove GLSL gamma texture
6915 case RENDERPATH_GL11:
6916 case RENDERPATH_GL13:
6917 case RENDERPATH_GLES1:
6922 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6923 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6929 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6930 if( scenetype != r_currentscenetype ) {
6931 // store the old scenetype
6932 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6933 r_currentscenetype = scenetype;
6934 // move in the new scene
6935 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6944 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6946 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6947 if( scenetype == r_currentscenetype ) {
6948 return &r_refdef.scene;
6950 return &r_scenes_store[ scenetype ];
6954 static int R_SortEntities_Compare(const void *ap, const void *bp)
6956 const entity_render_t *a = *(const entity_render_t **)ap;
6957 const entity_render_t *b = *(const entity_render_t **)bp;
6960 if(a->model < b->model)
6962 if(a->model > b->model)
6966 // TODO possibly calculate the REAL skinnum here first using
6968 if(a->skinnum < b->skinnum)
6970 if(a->skinnum > b->skinnum)
6973 // everything we compared is equal
6976 static void R_SortEntities(void)
6978 // below or equal 2 ents, sorting never gains anything
6979 if(r_refdef.scene.numentities <= 2)
6982 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6990 int dpsoftrast_test;
6991 extern cvar_t r_shadow_bouncegrid;
6992 void R_RenderView(void)
6994 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6996 rtexture_t *depthtexture;
6997 rtexture_t *colortexture;
6999 dpsoftrast_test = r_test.integer;
7001 if (r_timereport_active)
7002 R_TimeReport("start");
7003 r_textureframe++; // used only by R_GetCurrentTexture
7004 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7006 if(R_CompileShader_CheckStaticParms())
7009 if (!r_drawentities.integer)
7010 r_refdef.scene.numentities = 0;
7011 else if (r_sortentities.integer)
7014 R_AnimCache_ClearCache();
7015 R_FrameData_NewFrame();
7017 /* adjust for stereo display */
7018 if(R_Stereo_Active())
7020 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);
7021 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7024 if (r_refdef.view.isoverlay)
7026 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7027 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7028 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7029 R_TimeReport("depthclear");
7031 r_refdef.view.showdebug = false;
7033 r_fb.water.enabled = false;
7034 r_fb.water.numwaterplanes = 0;
7036 R_RenderScene(0, NULL, NULL);
7038 r_refdef.view.matrix = originalmatrix;
7044 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7046 r_refdef.view.matrix = originalmatrix;
7050 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7052 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7053 // in sRGB fallback, behave similar to true sRGB: convert this
7054 // value from linear to sRGB
7055 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7057 R_RenderView_UpdateViewVectors();
7059 R_Shadow_UpdateWorldLightSelection();
7061 R_Bloom_StartFrame();
7063 // apply bloom brightness offset
7064 if(r_fb.bloomtexture[0])
7065 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7067 R_Water_StartFrame();
7069 // now we probably have an fbo to render into
7071 depthtexture = r_fb.depthtexture;
7072 colortexture = r_fb.colortexture;
7075 if (r_timereport_active)
7076 R_TimeReport("viewsetup");
7078 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7080 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7082 R_ClearScreen(r_refdef.fogenabled);
7083 if (r_timereport_active)
7084 R_TimeReport("viewclear");
7086 r_refdef.view.clear = true;
7088 r_refdef.view.showdebug = true;
7091 if (r_timereport_active)
7092 R_TimeReport("visibility");
7094 R_AnimCache_CacheVisibleEntities();
7095 if (r_timereport_active)
7096 R_TimeReport("animcache");
7098 R_Shadow_UpdateBounceGridTexture();
7099 if (r_timereport_active && r_shadow_bouncegrid.integer)
7100 R_TimeReport("bouncegrid");
7102 r_fb.water.numwaterplanes = 0;
7103 if (r_fb.water.enabled)
7104 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7106 R_RenderScene(fbo, depthtexture, colortexture);
7107 r_fb.water.numwaterplanes = 0;
7109 R_BlendView(fbo, depthtexture, colortexture);
7110 if (r_timereport_active)
7111 R_TimeReport("blendview");
7113 GL_Scissor(0, 0, vid.width, vid.height);
7114 GL_ScissorTest(false);
7116 r_refdef.view.matrix = originalmatrix;
7121 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7123 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7125 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7126 if (r_timereport_active)
7127 R_TimeReport("waterworld");
7130 // don't let sound skip if going slow
7131 if (r_refdef.scene.extraupdate)
7134 R_DrawModelsAddWaterPlanes();
7135 if (r_timereport_active)
7136 R_TimeReport("watermodels");
7138 if (r_fb.water.numwaterplanes)
7140 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7141 if (r_timereport_active)
7142 R_TimeReport("waterscenes");
7146 extern cvar_t cl_locs_show;
7147 static void R_DrawLocs(void);
7148 static void R_DrawEntityBBoxes(void);
7149 static void R_DrawModelDecals(void);
7150 extern cvar_t cl_decals_newsystem;
7151 extern qboolean r_shadow_usingdeferredprepass;
7152 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7154 qboolean shadowmapping = false;
7156 if (r_timereport_active)
7157 R_TimeReport("beginscene");
7159 r_refdef.stats.renders++;
7163 // don't let sound skip if going slow
7164 if (r_refdef.scene.extraupdate)
7167 R_MeshQueue_BeginScene();
7171 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);
7173 if (r_timereport_active)
7174 R_TimeReport("skystartframe");
7176 if (cl.csqc_vidvars.drawworld)
7178 // don't let sound skip if going slow
7179 if (r_refdef.scene.extraupdate)
7182 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7184 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7185 if (r_timereport_active)
7186 R_TimeReport("worldsky");
7189 if (R_DrawBrushModelsSky() && r_timereport_active)
7190 R_TimeReport("bmodelsky");
7192 if (skyrendermasked && skyrenderlater)
7194 // we have to force off the water clipping plane while rendering sky
7195 R_SetupView(false, fbo, depthtexture, colortexture);
7197 R_SetupView(true, fbo, depthtexture, colortexture);
7198 if (r_timereport_active)
7199 R_TimeReport("sky");
7203 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7204 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7205 R_Shadow_PrepareModelShadows();
7206 if (r_timereport_active)
7207 R_TimeReport("preparelights");
7209 if (R_Shadow_ShadowMappingEnabled())
7210 shadowmapping = true;
7212 if (r_shadow_usingdeferredprepass)
7213 R_Shadow_DrawPrepass();
7215 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7217 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7218 if (r_timereport_active)
7219 R_TimeReport("worlddepth");
7221 if (r_depthfirst.integer >= 2)
7223 R_DrawModelsDepth();
7224 if (r_timereport_active)
7225 R_TimeReport("modeldepth");
7228 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7230 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7231 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7232 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7233 // don't let sound skip if going slow
7234 if (r_refdef.scene.extraupdate)
7238 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7240 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7241 if (r_timereport_active)
7242 R_TimeReport("world");
7245 // don't let sound skip if going slow
7246 if (r_refdef.scene.extraupdate)
7250 if (r_timereport_active)
7251 R_TimeReport("models");
7253 // don't let sound skip if going slow
7254 if (r_refdef.scene.extraupdate)
7257 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7259 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7260 R_DrawModelShadows(fbo, depthtexture, colortexture);
7261 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7262 // don't let sound skip if going slow
7263 if (r_refdef.scene.extraupdate)
7267 if (!r_shadow_usingdeferredprepass)
7269 R_Shadow_DrawLights();
7270 if (r_timereport_active)
7271 R_TimeReport("rtlights");
7274 // don't let sound skip if going slow
7275 if (r_refdef.scene.extraupdate)
7278 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7280 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7281 R_DrawModelShadows(fbo, depthtexture, colortexture);
7282 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7283 // don't let sound skip if going slow
7284 if (r_refdef.scene.extraupdate)
7288 if (cl.csqc_vidvars.drawworld)
7290 if (cl_decals_newsystem.integer)
7292 R_DrawModelDecals();
7293 if (r_timereport_active)
7294 R_TimeReport("modeldecals");
7299 if (r_timereport_active)
7300 R_TimeReport("decals");
7304 if (r_timereport_active)
7305 R_TimeReport("particles");
7308 if (r_timereport_active)
7309 R_TimeReport("explosions");
7311 R_DrawLightningBeams();
7312 if (r_timereport_active)
7313 R_TimeReport("lightning");
7317 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7319 if (r_refdef.view.showdebug)
7321 if (cl_locs_show.integer)
7324 if (r_timereport_active)
7325 R_TimeReport("showlocs");
7328 if (r_drawportals.integer)
7331 if (r_timereport_active)
7332 R_TimeReport("portals");
7335 if (r_showbboxes.value > 0)
7337 R_DrawEntityBBoxes();
7338 if (r_timereport_active)
7339 R_TimeReport("bboxes");
7343 if (r_transparent.integer)
7345 R_MeshQueue_RenderTransparent();
7346 if (r_timereport_active)
7347 R_TimeReport("drawtrans");
7350 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))
7352 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7353 if (r_timereport_active)
7354 R_TimeReport("worlddebug");
7355 R_DrawModelsDebug();
7356 if (r_timereport_active)
7357 R_TimeReport("modeldebug");
7360 if (cl.csqc_vidvars.drawworld)
7362 R_Shadow_DrawCoronas();
7363 if (r_timereport_active)
7364 R_TimeReport("coronas");
7369 GL_DepthTest(false);
7370 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7371 GL_Color(1, 1, 1, 1);
7372 qglBegin(GL_POLYGON);
7373 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7374 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7375 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7376 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7378 qglBegin(GL_POLYGON);
7379 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]);
7380 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]);
7381 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]);
7382 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]);
7384 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7388 // don't let sound skip if going slow
7389 if (r_refdef.scene.extraupdate)
7393 static const unsigned short bboxelements[36] =
7403 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7406 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7408 RSurf_ActiveWorldEntity();
7410 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7411 GL_DepthMask(false);
7412 GL_DepthRange(0, 1);
7413 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7414 // R_Mesh_ResetTextureState();
7416 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7417 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7418 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7419 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7420 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7421 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7422 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7423 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7424 R_FillColors(color4f, 8, cr, cg, cb, ca);
7425 if (r_refdef.fogenabled)
7427 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7429 f1 = RSurf_FogVertex(v);
7431 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7432 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7433 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7436 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7437 R_Mesh_ResetTextureState();
7438 R_SetupShader_Generic_NoTexture(false, false);
7439 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7442 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7444 prvm_prog_t *prog = SVVM_prog;
7447 prvm_edict_t *edict;
7449 // this function draws bounding boxes of server entities
7453 GL_CullFace(GL_NONE);
7454 R_SetupShader_Generic_NoTexture(false, false);
7456 for (i = 0;i < numsurfaces;i++)
7458 edict = PRVM_EDICT_NUM(surfacelist[i]);
7459 switch ((int)PRVM_serveredictfloat(edict, solid))
7461 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7462 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7463 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7464 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7465 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7466 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7467 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7469 color[3] *= r_showbboxes.value;
7470 color[3] = bound(0, color[3], 1);
7471 GL_DepthTest(!r_showdisabledepthtest.integer);
7472 GL_CullFace(r_refdef.view.cullface_front);
7473 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7477 static void R_DrawEntityBBoxes(void)
7480 prvm_edict_t *edict;
7482 prvm_prog_t *prog = SVVM_prog;
7484 // this function draws bounding boxes of server entities
7488 for (i = 0;i < prog->num_edicts;i++)
7490 edict = PRVM_EDICT_NUM(i);
7491 if (edict->priv.server->free)
7493 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7494 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7496 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7498 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7499 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7503 static const int nomodelelement3i[24] =
7515 static const unsigned short nomodelelement3s[24] =
7527 static const float nomodelvertex3f[6*3] =
7537 static const float nomodelcolor4f[6*4] =
7539 0.0f, 0.0f, 0.5f, 1.0f,
7540 0.0f, 0.0f, 0.5f, 1.0f,
7541 0.0f, 0.5f, 0.0f, 1.0f,
7542 0.0f, 0.5f, 0.0f, 1.0f,
7543 0.5f, 0.0f, 0.0f, 1.0f,
7544 0.5f, 0.0f, 0.0f, 1.0f
7547 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7553 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);
7555 // this is only called once per entity so numsurfaces is always 1, and
7556 // surfacelist is always {0}, so this code does not handle batches
7558 if (rsurface.ent_flags & RENDER_ADDITIVE)
7560 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7561 GL_DepthMask(false);
7563 else if (rsurface.colormod[3] < 1)
7565 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7566 GL_DepthMask(false);
7570 GL_BlendFunc(GL_ONE, GL_ZERO);
7573 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7574 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7575 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7576 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7577 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7578 for (i = 0, c = color4f;i < 6;i++, c += 4)
7580 c[0] *= rsurface.colormod[0];
7581 c[1] *= rsurface.colormod[1];
7582 c[2] *= rsurface.colormod[2];
7583 c[3] *= rsurface.colormod[3];
7585 if (r_refdef.fogenabled)
7587 for (i = 0, c = color4f;i < 6;i++, c += 4)
7589 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7591 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7592 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7593 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7596 // R_Mesh_ResetTextureState();
7597 R_SetupShader_Generic_NoTexture(false, false);
7598 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7599 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7602 void R_DrawNoModel(entity_render_t *ent)
7605 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7606 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7607 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7609 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7612 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7614 vec3_t right1, right2, diff, normal;
7616 VectorSubtract (org2, org1, normal);
7618 // calculate 'right' vector for start
7619 VectorSubtract (r_refdef.view.origin, org1, diff);
7620 CrossProduct (normal, diff, right1);
7621 VectorNormalize (right1);
7623 // calculate 'right' vector for end
7624 VectorSubtract (r_refdef.view.origin, org2, diff);
7625 CrossProduct (normal, diff, right2);
7626 VectorNormalize (right2);
7628 vert[ 0] = org1[0] + width * right1[0];
7629 vert[ 1] = org1[1] + width * right1[1];
7630 vert[ 2] = org1[2] + width * right1[2];
7631 vert[ 3] = org1[0] - width * right1[0];
7632 vert[ 4] = org1[1] - width * right1[1];
7633 vert[ 5] = org1[2] - width * right1[2];
7634 vert[ 6] = org2[0] - width * right2[0];
7635 vert[ 7] = org2[1] - width * right2[1];
7636 vert[ 8] = org2[2] - width * right2[2];
7637 vert[ 9] = org2[0] + width * right2[0];
7638 vert[10] = org2[1] + width * right2[1];
7639 vert[11] = org2[2] + width * right2[2];
7642 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)
7644 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7645 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7646 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7647 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7648 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7649 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7650 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7651 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7652 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7653 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7654 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7655 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7658 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7663 VectorSet(v, x, y, z);
7664 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7665 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7667 if (i == mesh->numvertices)
7669 if (mesh->numvertices < mesh->maxvertices)
7671 VectorCopy(v, vertex3f);
7672 mesh->numvertices++;
7674 return mesh->numvertices;
7680 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7684 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7685 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7686 e = mesh->element3i + mesh->numtriangles * 3;
7687 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7689 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7690 if (mesh->numtriangles < mesh->maxtriangles)
7695 mesh->numtriangles++;
7697 element[1] = element[2];
7701 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7705 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7706 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7707 e = mesh->element3i + mesh->numtriangles * 3;
7708 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7710 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7711 if (mesh->numtriangles < mesh->maxtriangles)
7716 mesh->numtriangles++;
7718 element[1] = element[2];
7722 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7723 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7725 int planenum, planenum2;
7728 mplane_t *plane, *plane2;
7730 double temppoints[2][256*3];
7731 // figure out how large a bounding box we need to properly compute this brush
7733 for (w = 0;w < numplanes;w++)
7734 maxdist = max(maxdist, fabs(planes[w].dist));
7735 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7736 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7737 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7741 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7742 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7744 if (planenum2 == planenum)
7746 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);
7749 if (tempnumpoints < 3)
7751 // generate elements forming a triangle fan for this polygon
7752 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7756 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)
7758 texturelayer_t *layer;
7759 layer = t->currentlayers + t->currentnumlayers++;
7761 layer->depthmask = depthmask;
7762 layer->blendfunc1 = blendfunc1;
7763 layer->blendfunc2 = blendfunc2;
7764 layer->texture = texture;
7765 layer->texmatrix = *matrix;
7766 layer->color[0] = r;
7767 layer->color[1] = g;
7768 layer->color[2] = b;
7769 layer->color[3] = a;
7772 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7774 if(parms[0] == 0 && parms[1] == 0)
7776 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7777 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7782 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7785 index = parms[2] + rsurface.shadertime * parms[3];
7786 index -= floor(index);
7787 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7790 case Q3WAVEFUNC_NONE:
7791 case Q3WAVEFUNC_NOISE:
7792 case Q3WAVEFUNC_COUNT:
7795 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7796 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7797 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7798 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7799 case Q3WAVEFUNC_TRIANGLE:
7801 f = index - floor(index);
7814 f = parms[0] + parms[1] * f;
7815 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7816 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7820 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7826 matrix4x4_t matrix, temp;
7827 switch(tcmod->tcmod)
7831 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7832 matrix = r_waterscrollmatrix;
7834 matrix = identitymatrix;
7836 case Q3TCMOD_ENTITYTRANSLATE:
7837 // this is used in Q3 to allow the gamecode to control texcoord
7838 // scrolling on the entity, which is not supported in darkplaces yet.
7839 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7841 case Q3TCMOD_ROTATE:
7842 f = tcmod->parms[0] * rsurface.shadertime;
7843 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7844 Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7845 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7848 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7850 case Q3TCMOD_SCROLL:
7851 // extra care is needed because of precision breakdown with large values of time
7852 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7853 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7854 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7856 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7857 w = (int) tcmod->parms[0];
7858 h = (int) tcmod->parms[1];
7859 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7861 idx = (int) floor(f * w * h);
7862 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7864 case Q3TCMOD_STRETCH:
7865 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7866 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7868 case Q3TCMOD_TRANSFORM:
7869 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7870 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7871 VectorSet(tcmat + 6, 0 , 0 , 1);
7872 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7873 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7875 case Q3TCMOD_TURBULENT:
7876 // this is handled in the RSurf_PrepareVertices function
7877 matrix = identitymatrix;
7881 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7884 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7886 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7887 char name[MAX_QPATH];
7888 skinframe_t *skinframe;
7889 unsigned char pixels[296*194];
7890 strlcpy(cache->name, skinname, sizeof(cache->name));
7891 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7892 if (developer_loading.integer)
7893 Con_Printf("loading %s\n", name);
7894 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7895 if (!skinframe || !skinframe->base)
7898 fs_offset_t filesize;
7900 f = FS_LoadFile(name, tempmempool, true, &filesize);
7903 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7904 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7908 cache->skinframe = skinframe;
7911 texture_t *R_GetCurrentTexture(texture_t *t)
7914 const entity_render_t *ent = rsurface.entity;
7915 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7916 q3shaderinfo_layer_tcmod_t *tcmod;
7918 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7919 return t->currentframe;
7920 t->update_lastrenderframe = r_textureframe;
7921 t->update_lastrenderentity = (void *)ent;
7923 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7924 t->camera_entity = ent->entitynumber;
7926 t->camera_entity = 0;
7928 // switch to an alternate material if this is a q1bsp animated material
7930 texture_t *texture = t;
7931 int s = rsurface.ent_skinnum;
7932 if ((unsigned int)s >= (unsigned int)model->numskins)
7934 if (model->skinscenes)
7936 if (model->skinscenes[s].framecount > 1)
7937 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7939 s = model->skinscenes[s].firstframe;
7942 t = t + s * model->num_surfaces;
7945 // use an alternate animation if the entity's frame is not 0,
7946 // and only if the texture has an alternate animation
7947 if (rsurface.ent_alttextures && t->anim_total[1])
7948 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7950 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7952 texture->currentframe = t;
7955 // update currentskinframe to be a qw skin or animation frame
7956 if (rsurface.ent_qwskin >= 0)
7958 i = rsurface.ent_qwskin;
7959 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7961 r_qwskincache_size = cl.maxclients;
7963 Mem_Free(r_qwskincache);
7964 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7966 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7967 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7968 t->currentskinframe = r_qwskincache[i].skinframe;
7969 if (t->currentskinframe == NULL)
7970 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7972 else if (t->numskinframes >= 2)
7973 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7974 if (t->backgroundnumskinframes >= 2)
7975 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7977 t->currentmaterialflags = t->basematerialflags;
7978 t->currentalpha = rsurface.colormod[3];
7979 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7980 t->currentalpha *= r_wateralpha.value;
7981 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7982 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7983 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7984 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7985 if (!(rsurface.ent_flags & RENDER_LIGHT))
7986 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7987 else if (FAKELIGHT_ENABLED)
7989 // no modellight if using fakelight for the map
7991 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7993 // pick a model lighting mode
7994 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7995 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7997 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7999 if (rsurface.ent_flags & RENDER_ADDITIVE)
8000 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8001 else if (t->currentalpha < 1)
8002 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8003 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8004 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8005 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8006 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8007 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8008 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8009 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8010 if (t->backgroundnumskinframes)
8011 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8012 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8014 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8015 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8018 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8019 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8021 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8022 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8024 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8025 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8027 // there is no tcmod
8028 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8030 t->currenttexmatrix = r_waterscrollmatrix;
8031 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8033 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8035 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8036 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8039 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8040 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8041 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8042 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8044 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8045 if (t->currentskinframe->qpixels)
8046 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8047 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8048 if (!t->basetexture)
8049 t->basetexture = r_texture_notexture;
8050 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8051 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8052 t->nmaptexture = t->currentskinframe->nmap;
8053 if (!t->nmaptexture)
8054 t->nmaptexture = r_texture_blanknormalmap;
8055 t->glosstexture = r_texture_black;
8056 t->glowtexture = t->currentskinframe->glow;
8057 t->fogtexture = t->currentskinframe->fog;
8058 t->reflectmasktexture = t->currentskinframe->reflect;
8059 if (t->backgroundnumskinframes)
8061 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8062 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8063 t->backgroundglosstexture = r_texture_black;
8064 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8065 if (!t->backgroundnmaptexture)
8066 t->backgroundnmaptexture = r_texture_blanknormalmap;
8067 // make sure that if glow is going to be used, both textures are not NULL
8068 if (!t->backgroundglowtexture && t->glowtexture)
8069 t->backgroundglowtexture = r_texture_black;
8070 if (!t->glowtexture && t->backgroundglowtexture)
8071 t->glowtexture = r_texture_black;
8075 t->backgroundbasetexture = r_texture_white;
8076 t->backgroundnmaptexture = r_texture_blanknormalmap;
8077 t->backgroundglosstexture = r_texture_black;
8078 t->backgroundglowtexture = NULL;
8080 t->specularpower = r_shadow_glossexponent.value;
8081 // TODO: store reference values for these in the texture?
8082 t->specularscale = 0;
8083 if (r_shadow_gloss.integer > 0)
8085 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8087 if (r_shadow_glossintensity.value > 0)
8089 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8090 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8091 t->specularscale = r_shadow_glossintensity.value;
8094 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8096 t->glosstexture = r_texture_white;
8097 t->backgroundglosstexture = r_texture_white;
8098 t->specularscale = r_shadow_gloss2intensity.value;
8099 t->specularpower = r_shadow_gloss2exponent.value;
8102 t->specularscale *= t->specularscalemod;
8103 t->specularpower *= t->specularpowermod;
8104 t->rtlightambient = 0;
8106 // lightmaps mode looks bad with dlights using actual texturing, so turn
8107 // off the colormap and glossmap, but leave the normalmap on as it still
8108 // accurately represents the shading involved
8109 if (gl_lightmaps.integer)
8111 t->basetexture = r_texture_grey128;
8112 t->pantstexture = r_texture_black;
8113 t->shirttexture = r_texture_black;
8114 if (gl_lightmaps.integer < 2)
8115 t->nmaptexture = r_texture_blanknormalmap;
8116 t->glosstexture = r_texture_black;
8117 t->glowtexture = NULL;
8118 t->fogtexture = NULL;
8119 t->reflectmasktexture = NULL;
8120 t->backgroundbasetexture = NULL;
8121 if (gl_lightmaps.integer < 2)
8122 t->backgroundnmaptexture = r_texture_blanknormalmap;
8123 t->backgroundglosstexture = r_texture_black;
8124 t->backgroundglowtexture = NULL;
8125 t->specularscale = 0;
8126 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8129 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8130 VectorClear(t->dlightcolor);
8131 t->currentnumlayers = 0;
8132 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8134 int blendfunc1, blendfunc2;
8136 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8138 blendfunc1 = GL_SRC_ALPHA;
8139 blendfunc2 = GL_ONE;
8141 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8143 blendfunc1 = GL_SRC_ALPHA;
8144 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8146 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8148 blendfunc1 = t->customblendfunc[0];
8149 blendfunc2 = t->customblendfunc[1];
8153 blendfunc1 = GL_ONE;
8154 blendfunc2 = GL_ZERO;
8156 // don't colormod evilblend textures
8157 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8158 VectorSet(t->lightmapcolor, 1, 1, 1);
8159 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8160 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8162 // fullbright is not affected by r_refdef.lightmapintensity
8163 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]);
8164 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8165 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]);
8166 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8167 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]);
8171 vec3_t ambientcolor;
8173 // set the color tint used for lights affecting this surface
8174 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8176 // q3bsp has no lightmap updates, so the lightstylevalue that
8177 // would normally be baked into the lightmap must be
8178 // applied to the color
8179 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8180 if (model->type == mod_brushq3)
8181 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8182 colorscale *= r_refdef.lightmapintensity;
8183 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8184 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8185 // basic lit geometry
8186 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]);
8187 // add pants/shirt if needed
8188 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8189 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]);
8190 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8191 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]);
8192 // now add ambient passes if needed
8193 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8195 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]);
8196 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8197 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]);
8198 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8199 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]);
8202 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8203 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]);
8204 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8206 // if this is opaque use alpha blend which will darken the earlier
8209 // if this is an alpha blended material, all the earlier passes
8210 // were darkened by fog already, so we only need to add the fog
8211 // color ontop through the fog mask texture
8213 // if this is an additive blended material, all the earlier passes
8214 // were darkened by fog already, and we should not add fog color
8215 // (because the background was not darkened, there is no fog color
8216 // that was lost behind it).
8217 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]);
8221 return t->currentframe;
8224 rsurfacestate_t rsurface;
8226 void RSurf_ActiveWorldEntity(void)
8228 dp_model_t *model = r_refdef.scene.worldmodel;
8229 //if (rsurface.entity == r_refdef.scene.worldentity)
8231 rsurface.entity = r_refdef.scene.worldentity;
8232 rsurface.skeleton = NULL;
8233 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8234 rsurface.ent_skinnum = 0;
8235 rsurface.ent_qwskin = -1;
8236 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8237 rsurface.shadertime = r_refdef.scene.time;
8238 rsurface.matrix = identitymatrix;
8239 rsurface.inversematrix = identitymatrix;
8240 rsurface.matrixscale = 1;
8241 rsurface.inversematrixscale = 1;
8242 R_EntityMatrix(&identitymatrix);
8243 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8244 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8245 rsurface.fograngerecip = r_refdef.fograngerecip;
8246 rsurface.fogheightfade = r_refdef.fogheightfade;
8247 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8248 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8249 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8250 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8251 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8252 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8253 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8254 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8255 rsurface.colormod[3] = 1;
8256 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);
8257 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8258 rsurface.frameblend[0].lerp = 1;
8259 rsurface.ent_alttextures = false;
8260 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8261 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8262 rsurface.entityskeletaltransform3x4 = NULL;
8263 rsurface.entityskeletalnumtransforms = 0;
8264 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8265 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8266 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8267 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8268 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8270 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8271 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8273 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8274 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8275 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8276 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8277 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8278 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8279 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8280 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8281 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8282 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8283 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8284 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8285 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8286 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8287 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8288 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8289 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8290 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8291 rsurface.modelelement3i = model->surfmesh.data_element3i;
8292 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8293 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8294 rsurface.modelelement3s = model->surfmesh.data_element3s;
8295 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8296 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8297 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8298 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8299 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8300 rsurface.modelsurfaces = model->data_surfaces;
8301 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8302 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8303 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8304 rsurface.modelgeneratedvertex = false;
8305 rsurface.batchgeneratedvertex = false;
8306 rsurface.batchfirstvertex = 0;
8307 rsurface.batchnumvertices = 0;
8308 rsurface.batchfirsttriangle = 0;
8309 rsurface.batchnumtriangles = 0;
8310 rsurface.batchvertex3f = NULL;
8311 rsurface.batchvertex3f_vertexbuffer = NULL;
8312 rsurface.batchvertex3f_bufferoffset = 0;
8313 rsurface.batchsvector3f = NULL;
8314 rsurface.batchsvector3f_vertexbuffer = NULL;
8315 rsurface.batchsvector3f_bufferoffset = 0;
8316 rsurface.batchtvector3f = NULL;
8317 rsurface.batchtvector3f_vertexbuffer = NULL;
8318 rsurface.batchtvector3f_bufferoffset = 0;
8319 rsurface.batchnormal3f = NULL;
8320 rsurface.batchnormal3f_vertexbuffer = NULL;
8321 rsurface.batchnormal3f_bufferoffset = 0;
8322 rsurface.batchlightmapcolor4f = NULL;
8323 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8324 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8325 rsurface.batchtexcoordtexture2f = NULL;
8326 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8327 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8328 rsurface.batchtexcoordlightmap2f = NULL;
8329 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8330 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8331 rsurface.batchskeletalindex4ub = NULL;
8332 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8333 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8334 rsurface.batchskeletalweight4ub = NULL;
8335 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8336 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8337 rsurface.batchvertexmesh = NULL;
8338 rsurface.batchvertexmeshbuffer = NULL;
8339 rsurface.batchvertex3fbuffer = NULL;
8340 rsurface.batchelement3i = NULL;
8341 rsurface.batchelement3i_indexbuffer = NULL;
8342 rsurface.batchelement3i_bufferoffset = 0;
8343 rsurface.batchelement3s = NULL;
8344 rsurface.batchelement3s_indexbuffer = NULL;
8345 rsurface.batchelement3s_bufferoffset = 0;
8346 rsurface.passcolor4f = NULL;
8347 rsurface.passcolor4f_vertexbuffer = NULL;
8348 rsurface.passcolor4f_bufferoffset = 0;
8349 rsurface.forcecurrenttextureupdate = false;
8352 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8354 dp_model_t *model = ent->model;
8355 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8357 rsurface.entity = (entity_render_t *)ent;
8358 rsurface.skeleton = ent->skeleton;
8359 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8360 rsurface.ent_skinnum = ent->skinnum;
8361 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;
8362 rsurface.ent_flags = ent->flags;
8363 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8364 rsurface.matrix = ent->matrix;
8365 rsurface.inversematrix = ent->inversematrix;
8366 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8367 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8368 R_EntityMatrix(&rsurface.matrix);
8369 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8370 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8371 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8372 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8373 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8374 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8375 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8376 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8377 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8378 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8379 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8380 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8381 rsurface.colormod[3] = ent->alpha;
8382 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8383 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8384 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8385 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8386 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8387 if (ent->model->brush.submodel && !prepass)
8389 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8390 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8392 // if the animcache code decided it should use the shader path, skip the deform step
8393 rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8394 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8395 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8397 if (ent->animcache_vertex3f)
8399 rsurface.modelvertex3f = ent->animcache_vertex3f;
8400 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8401 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8402 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8403 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8404 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8405 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8407 else if (wanttangents)
8409 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8410 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8411 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8412 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8413 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8414 rsurface.modelvertexmesh = NULL;
8415 rsurface.modelvertexmeshbuffer = NULL;
8416 rsurface.modelvertex3fbuffer = NULL;
8418 else if (wantnormals)
8420 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8421 rsurface.modelsvector3f = NULL;
8422 rsurface.modeltvector3f = NULL;
8423 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8424 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8425 rsurface.modelvertexmesh = NULL;
8426 rsurface.modelvertexmeshbuffer = NULL;
8427 rsurface.modelvertex3fbuffer = NULL;
8431 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8432 rsurface.modelsvector3f = NULL;
8433 rsurface.modeltvector3f = NULL;
8434 rsurface.modelnormal3f = NULL;
8435 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8436 rsurface.modelvertexmesh = NULL;
8437 rsurface.modelvertexmeshbuffer = NULL;
8438 rsurface.modelvertex3fbuffer = NULL;
8440 rsurface.modelvertex3f_vertexbuffer = 0;
8441 rsurface.modelvertex3f_bufferoffset = 0;
8442 rsurface.modelsvector3f_vertexbuffer = 0;
8443 rsurface.modelsvector3f_bufferoffset = 0;
8444 rsurface.modeltvector3f_vertexbuffer = 0;
8445 rsurface.modeltvector3f_bufferoffset = 0;
8446 rsurface.modelnormal3f_vertexbuffer = 0;
8447 rsurface.modelnormal3f_bufferoffset = 0;
8448 rsurface.modelgeneratedvertex = true;
8452 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8453 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8454 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8455 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8456 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8457 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8458 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8459 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8460 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8461 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8462 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8463 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8464 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8465 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8466 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8467 rsurface.modelgeneratedvertex = false;
8469 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8470 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8471 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8472 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8473 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8474 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8475 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8476 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8477 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8478 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8479 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8480 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8481 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8482 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8483 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8484 rsurface.modelelement3i = model->surfmesh.data_element3i;
8485 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8486 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8487 rsurface.modelelement3s = model->surfmesh.data_element3s;
8488 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8489 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8490 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8491 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8492 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8493 rsurface.modelsurfaces = model->data_surfaces;
8494 rsurface.batchgeneratedvertex = false;
8495 rsurface.batchfirstvertex = 0;
8496 rsurface.batchnumvertices = 0;
8497 rsurface.batchfirsttriangle = 0;
8498 rsurface.batchnumtriangles = 0;
8499 rsurface.batchvertex3f = NULL;
8500 rsurface.batchvertex3f_vertexbuffer = NULL;
8501 rsurface.batchvertex3f_bufferoffset = 0;
8502 rsurface.batchsvector3f = NULL;
8503 rsurface.batchsvector3f_vertexbuffer = NULL;
8504 rsurface.batchsvector3f_bufferoffset = 0;
8505 rsurface.batchtvector3f = NULL;
8506 rsurface.batchtvector3f_vertexbuffer = NULL;
8507 rsurface.batchtvector3f_bufferoffset = 0;
8508 rsurface.batchnormal3f = NULL;
8509 rsurface.batchnormal3f_vertexbuffer = NULL;
8510 rsurface.batchnormal3f_bufferoffset = 0;
8511 rsurface.batchlightmapcolor4f = NULL;
8512 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8513 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8514 rsurface.batchtexcoordtexture2f = NULL;
8515 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8516 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8517 rsurface.batchtexcoordlightmap2f = NULL;
8518 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8519 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8520 rsurface.batchskeletalindex4ub = NULL;
8521 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8522 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8523 rsurface.batchskeletalweight4ub = NULL;
8524 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8525 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8526 rsurface.batchvertexmesh = NULL;
8527 rsurface.batchvertexmeshbuffer = NULL;
8528 rsurface.batchvertex3fbuffer = NULL;
8529 rsurface.batchelement3i = NULL;
8530 rsurface.batchelement3i_indexbuffer = NULL;
8531 rsurface.batchelement3i_bufferoffset = 0;
8532 rsurface.batchelement3s = NULL;
8533 rsurface.batchelement3s_indexbuffer = NULL;
8534 rsurface.batchelement3s_bufferoffset = 0;
8535 rsurface.passcolor4f = NULL;
8536 rsurface.passcolor4f_vertexbuffer = NULL;
8537 rsurface.passcolor4f_bufferoffset = 0;
8538 rsurface.forcecurrenttextureupdate = false;
8541 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)
8543 rsurface.entity = r_refdef.scene.worldentity;
8544 rsurface.skeleton = NULL;
8545 rsurface.ent_skinnum = 0;
8546 rsurface.ent_qwskin = -1;
8547 rsurface.ent_flags = entflags;
8548 rsurface.shadertime = r_refdef.scene.time - shadertime;
8549 rsurface.modelnumvertices = numvertices;
8550 rsurface.modelnumtriangles = numtriangles;
8551 rsurface.matrix = *matrix;
8552 rsurface.inversematrix = *inversematrix;
8553 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8554 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8555 R_EntityMatrix(&rsurface.matrix);
8556 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8557 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8558 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8559 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8560 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8561 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8562 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8563 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8564 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8565 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8566 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8567 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8568 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);
8569 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8570 rsurface.frameblend[0].lerp = 1;
8571 rsurface.ent_alttextures = false;
8572 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8573 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8574 rsurface.entityskeletaltransform3x4 = NULL;
8575 rsurface.entityskeletalnumtransforms = 0;
8578 rsurface.modelvertex3f = (float *)vertex3f;
8579 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8580 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8581 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8583 else if (wantnormals)
8585 rsurface.modelvertex3f = (float *)vertex3f;
8586 rsurface.modelsvector3f = NULL;
8587 rsurface.modeltvector3f = NULL;
8588 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8592 rsurface.modelvertex3f = (float *)vertex3f;
8593 rsurface.modelsvector3f = NULL;
8594 rsurface.modeltvector3f = NULL;
8595 rsurface.modelnormal3f = NULL;
8597 rsurface.modelvertexmesh = NULL;
8598 rsurface.modelvertexmeshbuffer = NULL;
8599 rsurface.modelvertex3fbuffer = NULL;
8600 rsurface.modelvertex3f_vertexbuffer = 0;
8601 rsurface.modelvertex3f_bufferoffset = 0;
8602 rsurface.modelsvector3f_vertexbuffer = 0;
8603 rsurface.modelsvector3f_bufferoffset = 0;
8604 rsurface.modeltvector3f_vertexbuffer = 0;
8605 rsurface.modeltvector3f_bufferoffset = 0;
8606 rsurface.modelnormal3f_vertexbuffer = 0;
8607 rsurface.modelnormal3f_bufferoffset = 0;
8608 rsurface.modelgeneratedvertex = true;
8609 rsurface.modellightmapcolor4f = (float *)color4f;
8610 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8611 rsurface.modellightmapcolor4f_bufferoffset = 0;
8612 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8613 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8614 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8615 rsurface.modeltexcoordlightmap2f = NULL;
8616 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8617 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8618 rsurface.modelskeletalindex4ub = NULL;
8619 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8620 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8621 rsurface.modelskeletalweight4ub = NULL;
8622 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8623 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8624 rsurface.modelelement3i = (int *)element3i;
8625 rsurface.modelelement3i_indexbuffer = NULL;
8626 rsurface.modelelement3i_bufferoffset = 0;
8627 rsurface.modelelement3s = (unsigned short *)element3s;
8628 rsurface.modelelement3s_indexbuffer = NULL;
8629 rsurface.modelelement3s_bufferoffset = 0;
8630 rsurface.modellightmapoffsets = NULL;
8631 rsurface.modelsurfaces = NULL;
8632 rsurface.batchgeneratedvertex = false;
8633 rsurface.batchfirstvertex = 0;
8634 rsurface.batchnumvertices = 0;
8635 rsurface.batchfirsttriangle = 0;
8636 rsurface.batchnumtriangles = 0;
8637 rsurface.batchvertex3f = NULL;
8638 rsurface.batchvertex3f_vertexbuffer = NULL;
8639 rsurface.batchvertex3f_bufferoffset = 0;
8640 rsurface.batchsvector3f = NULL;
8641 rsurface.batchsvector3f_vertexbuffer = NULL;
8642 rsurface.batchsvector3f_bufferoffset = 0;
8643 rsurface.batchtvector3f = NULL;
8644 rsurface.batchtvector3f_vertexbuffer = NULL;
8645 rsurface.batchtvector3f_bufferoffset = 0;
8646 rsurface.batchnormal3f = NULL;
8647 rsurface.batchnormal3f_vertexbuffer = NULL;
8648 rsurface.batchnormal3f_bufferoffset = 0;
8649 rsurface.batchlightmapcolor4f = NULL;
8650 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8651 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8652 rsurface.batchtexcoordtexture2f = NULL;
8653 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8654 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8655 rsurface.batchtexcoordlightmap2f = NULL;
8656 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8657 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8658 rsurface.batchskeletalindex4ub = NULL;
8659 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8660 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8661 rsurface.batchskeletalweight4ub = NULL;
8662 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8663 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8664 rsurface.batchvertexmesh = NULL;
8665 rsurface.batchvertexmeshbuffer = NULL;
8666 rsurface.batchvertex3fbuffer = NULL;
8667 rsurface.batchelement3i = NULL;
8668 rsurface.batchelement3i_indexbuffer = NULL;
8669 rsurface.batchelement3i_bufferoffset = 0;
8670 rsurface.batchelement3s = NULL;
8671 rsurface.batchelement3s_indexbuffer = NULL;
8672 rsurface.batchelement3s_bufferoffset = 0;
8673 rsurface.passcolor4f = NULL;
8674 rsurface.passcolor4f_vertexbuffer = NULL;
8675 rsurface.passcolor4f_bufferoffset = 0;
8676 rsurface.forcecurrenttextureupdate = true;
8678 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8680 if ((wantnormals || wanttangents) && !normal3f)
8682 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8683 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8685 if (wanttangents && !svector3f)
8687 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8688 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8689 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8694 float RSurf_FogPoint(const float *v)
8696 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8697 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8698 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8699 float FogHeightFade = r_refdef.fogheightfade;
8701 unsigned int fogmasktableindex;
8702 if (r_refdef.fogplaneviewabove)
8703 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8705 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8706 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8707 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8710 float RSurf_FogVertex(const float *v)
8712 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8713 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8714 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8715 float FogHeightFade = rsurface.fogheightfade;
8717 unsigned int fogmasktableindex;
8718 if (r_refdef.fogplaneviewabove)
8719 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8721 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8722 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8723 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8726 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8729 for (i = 0;i < numelements;i++)
8730 outelement3i[i] = inelement3i[i] + adjust;
8733 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8734 extern cvar_t gl_vbo;
8735 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8743 int surfacefirsttriangle;
8744 int surfacenumtriangles;
8745 int surfacefirstvertex;
8746 int surfaceendvertex;
8747 int surfacenumvertices;
8748 int batchnumvertices;
8749 int batchnumtriangles;
8753 qboolean dynamicvertex;
8757 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8760 q3shaderinfo_deform_t *deform;
8761 const msurface_t *surface, *firstsurface;
8762 r_vertexmesh_t *vertexmesh;
8763 if (!texturenumsurfaces)
8765 // find vertex range of this surface batch
8767 firstsurface = texturesurfacelist[0];
8768 firsttriangle = firstsurface->num_firsttriangle;
8769 batchnumvertices = 0;
8770 batchnumtriangles = 0;
8771 firstvertex = endvertex = firstsurface->num_firstvertex;
8772 for (i = 0;i < texturenumsurfaces;i++)
8774 surface = texturesurfacelist[i];
8775 if (surface != firstsurface + i)
8777 surfacefirstvertex = surface->num_firstvertex;
8778 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8779 surfacenumvertices = surface->num_vertices;
8780 surfacenumtriangles = surface->num_triangles;
8781 if (firstvertex > surfacefirstvertex)
8782 firstvertex = surfacefirstvertex;
8783 if (endvertex < surfaceendvertex)
8784 endvertex = surfaceendvertex;
8785 batchnumvertices += surfacenumvertices;
8786 batchnumtriangles += surfacenumtriangles;
8789 // we now know the vertex range used, and if there are any gaps in it
8790 rsurface.batchfirstvertex = firstvertex;
8791 rsurface.batchnumvertices = endvertex - firstvertex;
8792 rsurface.batchfirsttriangle = firsttriangle;
8793 rsurface.batchnumtriangles = batchnumtriangles;
8795 // this variable holds flags for which properties have been updated that
8796 // may require regenerating vertexmesh array...
8799 // check if any dynamic vertex processing must occur
8800 dynamicvertex = false;
8802 // a cvar to force the dynamic vertex path to be taken, for debugging
8803 if (r_batch_debugdynamicvertexpath.integer)
8804 dynamicvertex = true;
8806 // if there is a chance of animated vertex colors, it's a dynamic batch
8807 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8809 dynamicvertex = true;
8810 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8813 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8815 switch (deform->deform)
8818 case Q3DEFORM_PROJECTIONSHADOW:
8819 case Q3DEFORM_TEXT0:
8820 case Q3DEFORM_TEXT1:
8821 case Q3DEFORM_TEXT2:
8822 case Q3DEFORM_TEXT3:
8823 case Q3DEFORM_TEXT4:
8824 case Q3DEFORM_TEXT5:
8825 case Q3DEFORM_TEXT6:
8826 case Q3DEFORM_TEXT7:
8829 case Q3DEFORM_AUTOSPRITE:
8830 dynamicvertex = true;
8831 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8832 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8834 case Q3DEFORM_AUTOSPRITE2:
8835 dynamicvertex = true;
8836 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8837 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8839 case Q3DEFORM_NORMAL:
8840 dynamicvertex = true;
8841 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8842 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8845 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8846 break; // if wavefunc is a nop, ignore this transform
8847 dynamicvertex = true;
8848 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8849 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8851 case Q3DEFORM_BULGE:
8852 dynamicvertex = true;
8853 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8854 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8857 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8858 break; // if wavefunc is a nop, ignore this transform
8859 dynamicvertex = true;
8860 batchneed |= BATCHNEED_ARRAY_VERTEX;
8861 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8865 switch(rsurface.texture->tcgen.tcgen)
8868 case Q3TCGEN_TEXTURE:
8870 case Q3TCGEN_LIGHTMAP:
8871 dynamicvertex = true;
8872 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8873 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8875 case Q3TCGEN_VECTOR:
8876 dynamicvertex = true;
8877 batchneed |= BATCHNEED_ARRAY_VERTEX;
8878 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8880 case Q3TCGEN_ENVIRONMENT:
8881 dynamicvertex = true;
8882 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8883 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8886 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8888 dynamicvertex = true;
8889 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8890 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8893 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8895 dynamicvertex = true;
8896 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8899 // when the model data has no vertex buffer (dynamic mesh), we need to
8901 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8902 batchneed |= BATCHNEED_NOGAPS;
8904 // the caller can specify BATCHNEED_NOGAPS to force a batch with
8905 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8906 // we ensure this by treating the vertex batch as dynamic...
8907 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8908 dynamicvertex = true;
8912 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8913 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8914 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8915 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8916 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8917 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8918 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8919 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
8922 // if needsupdate, we have to do a dynamic vertex batch for sure
8923 if (needsupdate & batchneed)
8924 dynamicvertex = true;
8926 // see if we need to build vertexmesh from arrays
8927 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8928 dynamicvertex = true;
8930 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
8931 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
8932 batchneed |= BATCHNEED_ARRAY_SKELETAL;
8934 rsurface.batchvertex3f = rsurface.modelvertex3f;
8935 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8936 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8937 rsurface.batchsvector3f = rsurface.modelsvector3f;
8938 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8939 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8940 rsurface.batchtvector3f = rsurface.modeltvector3f;
8941 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8942 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8943 rsurface.batchnormal3f = rsurface.modelnormal3f;
8944 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8945 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8946 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8947 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8948 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8949 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8950 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8951 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8952 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8953 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8954 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8955 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8956 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8957 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8958 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8959 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8960 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8961 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8962 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8963 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8964 rsurface.batchelement3i = rsurface.modelelement3i;
8965 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8966 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8967 rsurface.batchelement3s = rsurface.modelelement3s;
8968 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8969 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8970 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
8971 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
8973 // if any dynamic vertex processing has to occur in software, we copy the
8974 // entire surface list together before processing to rebase the vertices
8975 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8977 // if any gaps exist and we do not have a static vertex buffer, we have to
8978 // copy the surface list together to avoid wasting upload bandwidth on the
8979 // vertices in the gaps.
8981 // if gaps exist and we have a static vertex buffer, we can choose whether
8982 // to combine the index buffer ranges into one dynamic index buffer or
8983 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8985 // in many cases the batch is reduced to one draw call.
8987 rsurface.batchmultidraw = false;
8988 rsurface.batchmultidrawnumsurfaces = 0;
8989 rsurface.batchmultidrawsurfacelist = NULL;
8993 // static vertex data, just set pointers...
8994 rsurface.batchgeneratedvertex = false;
8995 // if there are gaps, we want to build a combined index buffer,
8996 // otherwise use the original static buffer with an appropriate offset
8999 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9001 rsurface.batchmultidraw = true;
9002 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9003 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9006 // build a new triangle elements array for this batch
9007 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9008 rsurface.batchfirsttriangle = 0;
9010 for (i = 0;i < texturenumsurfaces;i++)
9012 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9013 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9014 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9015 numtriangles += surfacenumtriangles;
9017 rsurface.batchelement3i_indexbuffer = NULL;
9018 rsurface.batchelement3i_bufferoffset = 0;
9019 rsurface.batchelement3s = NULL;
9020 rsurface.batchelement3s_indexbuffer = NULL;
9021 rsurface.batchelement3s_bufferoffset = 0;
9022 if (endvertex <= 65536)
9024 // make a 16bit (unsigned short) index array if possible
9025 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9026 for (i = 0;i < numtriangles*3;i++)
9027 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9033 // something needs software processing, do it for real...
9034 // we only directly handle separate array data in this case and then
9035 // generate interleaved data if needed...
9036 rsurface.batchgeneratedvertex = true;
9038 // now copy the vertex data into a combined array and make an index array
9039 // (this is what Quake3 does all the time)
9040 // we also apply any skeletal animation here that would have been done in
9041 // the vertex shader, because most of the dynamic vertex animation cases
9042 // need actual vertex positions and normals
9043 //if (dynamicvertex)
9045 rsurface.batchvertex3fbuffer = NULL;
9046 rsurface.batchvertexmesh = NULL;
9047 rsurface.batchvertexmeshbuffer = NULL;
9048 rsurface.batchvertex3f = NULL;
9049 rsurface.batchvertex3f_vertexbuffer = NULL;
9050 rsurface.batchvertex3f_bufferoffset = 0;
9051 rsurface.batchsvector3f = NULL;
9052 rsurface.batchsvector3f_vertexbuffer = NULL;
9053 rsurface.batchsvector3f_bufferoffset = 0;
9054 rsurface.batchtvector3f = NULL;
9055 rsurface.batchtvector3f_vertexbuffer = NULL;
9056 rsurface.batchtvector3f_bufferoffset = 0;
9057 rsurface.batchnormal3f = NULL;
9058 rsurface.batchnormal3f_vertexbuffer = NULL;
9059 rsurface.batchnormal3f_bufferoffset = 0;
9060 rsurface.batchlightmapcolor4f = NULL;
9061 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9062 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9063 rsurface.batchtexcoordtexture2f = NULL;
9064 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9065 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9066 rsurface.batchtexcoordlightmap2f = NULL;
9067 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9068 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9069 rsurface.batchskeletalindex4ub = NULL;
9070 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9071 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9072 rsurface.batchskeletalweight4ub = NULL;
9073 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9074 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9075 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9076 rsurface.batchelement3i_indexbuffer = NULL;
9077 rsurface.batchelement3i_bufferoffset = 0;
9078 rsurface.batchelement3s = NULL;
9079 rsurface.batchelement3s_indexbuffer = NULL;
9080 rsurface.batchelement3s_bufferoffset = 0;
9081 // we'll only be setting up certain arrays as needed
9082 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9083 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9084 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9085 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9086 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9087 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9088 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9090 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9091 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9093 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9094 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9095 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9096 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9097 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9098 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9099 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9101 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9102 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9106 for (i = 0;i < texturenumsurfaces;i++)
9108 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9109 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9110 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9111 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9112 // copy only the data requested
9113 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9114 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9115 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9117 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9119 if (rsurface.batchvertex3f)
9120 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9122 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9124 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9126 if (rsurface.modelnormal3f)
9127 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9129 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9131 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9133 if (rsurface.modelsvector3f)
9135 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9136 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9140 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9141 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9144 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9146 if (rsurface.modellightmapcolor4f)
9147 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9149 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9151 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9153 if (rsurface.modeltexcoordtexture2f)
9154 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9156 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9158 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9160 if (rsurface.modeltexcoordlightmap2f)
9161 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9163 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9165 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9167 if (rsurface.modelskeletalindex4ub)
9169 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9170 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9174 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9175 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9176 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9177 for (j = 0;j < surfacenumvertices;j++)
9182 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9183 numvertices += surfacenumvertices;
9184 numtriangles += surfacenumtriangles;
9187 // generate a 16bit index array as well if possible
9188 // (in general, dynamic batches fit)
9189 if (numvertices <= 65536)
9191 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9192 for (i = 0;i < numtriangles*3;i++)
9193 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9196 // since we've copied everything, the batch now starts at 0
9197 rsurface.batchfirstvertex = 0;
9198 rsurface.batchnumvertices = batchnumvertices;
9199 rsurface.batchfirsttriangle = 0;
9200 rsurface.batchnumtriangles = batchnumtriangles;
9203 // apply skeletal animation that would have been done in the vertex shader
9204 if (rsurface.batchskeletaltransform3x4)
9206 const unsigned char *si;
9207 const unsigned char *sw;
9209 const float *b = rsurface.batchskeletaltransform3x4;
9210 float *vp, *vs, *vt, *vn;
9212 float m[3][4], n[3][4];
9213 float tp[3], ts[3], tt[3], tn[3];
9214 si = rsurface.batchskeletalindex4ub;
9215 sw = rsurface.batchskeletalweight4ub;
9216 vp = rsurface.batchvertex3f;
9217 vs = rsurface.batchsvector3f;
9218 vt = rsurface.batchtvector3f;
9219 vn = rsurface.batchnormal3f;
9220 memset(m[0], 0, sizeof(m));
9221 memset(n[0], 0, sizeof(n));
9222 for (i = 0;i < batchnumvertices;i++)
9224 t[0] = b + si[0]*12;
9227 // common case - only one matrix
9241 else if (sw[2] + sw[3])
9244 t[1] = b + si[1]*12;
9245 t[2] = b + si[2]*12;
9246 t[3] = b + si[3]*12;
9247 w[0] = sw[0] * (1.0f / 255.0f);
9248 w[1] = sw[1] * (1.0f / 255.0f);
9249 w[2] = sw[2] * (1.0f / 255.0f);
9250 w[3] = sw[3] * (1.0f / 255.0f);
9251 // blend the matrices
9252 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9253 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9254 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9255 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9256 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9257 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9258 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9259 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9260 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9261 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9262 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9263 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9268 t[1] = b + si[1]*12;
9269 w[0] = sw[0] * (1.0f / 255.0f);
9270 w[1] = sw[1] * (1.0f / 255.0f);
9271 // blend the matrices
9272 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9273 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9274 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9275 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9276 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9277 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9278 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9279 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9280 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9281 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9282 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9283 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9287 // modify the vertex
9289 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9290 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9291 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9295 // the normal transformation matrix is a set of cross products...
9296 CrossProduct(m[1], m[2], n[0]);
9297 CrossProduct(m[2], m[0], n[1]);
9298 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9300 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9301 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9302 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9303 VectorNormalize(vn);
9308 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9309 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9310 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9311 VectorNormalize(vs);
9314 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9315 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9316 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9317 VectorNormalize(vt);
9322 rsurface.batchskeletaltransform3x4 = NULL;
9323 rsurface.batchskeletalnumtransforms = 0;
9326 // q1bsp surfaces rendered in vertex color mode have to have colors
9327 // calculated based on lightstyles
9328 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9330 // generate color arrays for the surfaces in this list
9335 const unsigned char *lm;
9336 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9337 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9338 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9340 for (i = 0;i < texturenumsurfaces;i++)
9342 surface = texturesurfacelist[i];
9343 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9344 surfacenumvertices = surface->num_vertices;
9345 if (surface->lightmapinfo->samples)
9347 for (j = 0;j < surfacenumvertices;j++)
9349 lm = surface->lightmapinfo->samples + offsets[j];
9350 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9351 VectorScale(lm, scale, c);
9352 if (surface->lightmapinfo->styles[1] != 255)
9354 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9356 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9357 VectorMA(c, scale, lm, c);
9358 if (surface->lightmapinfo->styles[2] != 255)
9361 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9362 VectorMA(c, scale, lm, c);
9363 if (surface->lightmapinfo->styles[3] != 255)
9366 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9367 VectorMA(c, scale, lm, c);
9374 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);
9380 for (j = 0;j < surfacenumvertices;j++)
9382 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9389 // if vertices are deformed (sprite flares and things in maps, possibly
9390 // water waves, bulges and other deformations), modify the copied vertices
9392 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9394 switch (deform->deform)
9397 case Q3DEFORM_PROJECTIONSHADOW:
9398 case Q3DEFORM_TEXT0:
9399 case Q3DEFORM_TEXT1:
9400 case Q3DEFORM_TEXT2:
9401 case Q3DEFORM_TEXT3:
9402 case Q3DEFORM_TEXT4:
9403 case Q3DEFORM_TEXT5:
9404 case Q3DEFORM_TEXT6:
9405 case Q3DEFORM_TEXT7:
9408 case Q3DEFORM_AUTOSPRITE:
9409 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9410 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9411 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9412 VectorNormalize(newforward);
9413 VectorNormalize(newright);
9414 VectorNormalize(newup);
9415 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9416 // rsurface.batchvertex3f_vertexbuffer = NULL;
9417 // rsurface.batchvertex3f_bufferoffset = 0;
9418 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9419 // rsurface.batchsvector3f_vertexbuffer = NULL;
9420 // rsurface.batchsvector3f_bufferoffset = 0;
9421 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9422 // rsurface.batchtvector3f_vertexbuffer = NULL;
9423 // rsurface.batchtvector3f_bufferoffset = 0;
9424 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9425 // rsurface.batchnormal3f_vertexbuffer = NULL;
9426 // rsurface.batchnormal3f_bufferoffset = 0;
9427 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9428 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9429 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9430 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9431 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);
9432 // a single autosprite surface can contain multiple sprites...
9433 for (j = 0;j < batchnumvertices - 3;j += 4)
9435 VectorClear(center);
9436 for (i = 0;i < 4;i++)
9437 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9438 VectorScale(center, 0.25f, center);
9439 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9440 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9441 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9442 for (i = 0;i < 4;i++)
9444 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9445 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9448 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9449 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9450 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);
9452 case Q3DEFORM_AUTOSPRITE2:
9453 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9454 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9455 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9456 VectorNormalize(newforward);
9457 VectorNormalize(newright);
9458 VectorNormalize(newup);
9459 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9460 // rsurface.batchvertex3f_vertexbuffer = NULL;
9461 // rsurface.batchvertex3f_bufferoffset = 0;
9463 const float *v1, *v2;
9473 memset(shortest, 0, sizeof(shortest));
9474 // a single autosprite surface can contain multiple sprites...
9475 for (j = 0;j < batchnumvertices - 3;j += 4)
9477 VectorClear(center);
9478 for (i = 0;i < 4;i++)
9479 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9480 VectorScale(center, 0.25f, center);
9481 // find the two shortest edges, then use them to define the
9482 // axis vectors for rotating around the central axis
9483 for (i = 0;i < 6;i++)
9485 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9486 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9487 l = VectorDistance2(v1, v2);
9488 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9490 l += (1.0f / 1024.0f);
9491 if (shortest[0].length2 > l || i == 0)
9493 shortest[1] = shortest[0];
9494 shortest[0].length2 = l;
9495 shortest[0].v1 = v1;
9496 shortest[0].v2 = v2;
9498 else if (shortest[1].length2 > l || i == 1)
9500 shortest[1].length2 = l;
9501 shortest[1].v1 = v1;
9502 shortest[1].v2 = v2;
9505 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9506 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9507 // this calculates the right vector from the shortest edge
9508 // and the up vector from the edge midpoints
9509 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9510 VectorNormalize(right);
9511 VectorSubtract(end, start, up);
9512 VectorNormalize(up);
9513 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9514 VectorSubtract(rsurface.localvieworigin, center, forward);
9515 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9516 VectorNegate(forward, forward);
9517 VectorReflect(forward, 0, up, forward);
9518 VectorNormalize(forward);
9519 CrossProduct(up, forward, newright);
9520 VectorNormalize(newright);
9521 // rotate the quad around the up axis vector, this is made
9522 // especially easy by the fact we know the quad is flat,
9523 // so we only have to subtract the center position and
9524 // measure distance along the right vector, and then
9525 // multiply that by the newright vector and add back the
9527 // we also need to subtract the old position to undo the
9528 // displacement from the center, which we do with a
9529 // DotProduct, the subtraction/addition of center is also
9530 // optimized into DotProducts here
9531 l = DotProduct(right, center);
9532 for (i = 0;i < 4;i++)
9534 v1 = rsurface.batchvertex3f + 3*(j+i);
9535 f = DotProduct(right, v1) - l;
9536 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9540 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9542 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9543 // rsurface.batchnormal3f_vertexbuffer = NULL;
9544 // rsurface.batchnormal3f_bufferoffset = 0;
9545 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9547 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9549 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9550 // rsurface.batchsvector3f_vertexbuffer = NULL;
9551 // rsurface.batchsvector3f_bufferoffset = 0;
9552 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9553 // rsurface.batchtvector3f_vertexbuffer = NULL;
9554 // rsurface.batchtvector3f_bufferoffset = 0;
9555 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);
9558 case Q3DEFORM_NORMAL:
9559 // deform the normals to make reflections wavey
9560 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9561 rsurface.batchnormal3f_vertexbuffer = NULL;
9562 rsurface.batchnormal3f_bufferoffset = 0;
9563 for (j = 0;j < batchnumvertices;j++)
9566 float *normal = rsurface.batchnormal3f + 3*j;
9567 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9568 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9569 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9570 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9571 VectorNormalize(normal);
9573 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9575 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9576 // rsurface.batchsvector3f_vertexbuffer = NULL;
9577 // rsurface.batchsvector3f_bufferoffset = 0;
9578 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9579 // rsurface.batchtvector3f_vertexbuffer = NULL;
9580 // rsurface.batchtvector3f_bufferoffset = 0;
9581 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);
9585 // deform vertex array to make wavey water and flags and such
9586 waveparms[0] = deform->waveparms[0];
9587 waveparms[1] = deform->waveparms[1];
9588 waveparms[2] = deform->waveparms[2];
9589 waveparms[3] = deform->waveparms[3];
9590 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9591 break; // if wavefunc is a nop, don't make a dynamic vertex array
9592 // this is how a divisor of vertex influence on deformation
9593 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9594 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9595 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9596 // rsurface.batchvertex3f_vertexbuffer = NULL;
9597 // rsurface.batchvertex3f_bufferoffset = 0;
9598 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9599 // rsurface.batchnormal3f_vertexbuffer = NULL;
9600 // rsurface.batchnormal3f_bufferoffset = 0;
9601 for (j = 0;j < batchnumvertices;j++)
9603 // if the wavefunc depends on time, evaluate it per-vertex
9606 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9607 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9609 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9611 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9612 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9613 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9615 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9616 // rsurface.batchsvector3f_vertexbuffer = NULL;
9617 // rsurface.batchsvector3f_bufferoffset = 0;
9618 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9619 // rsurface.batchtvector3f_vertexbuffer = NULL;
9620 // rsurface.batchtvector3f_bufferoffset = 0;
9621 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);
9624 case Q3DEFORM_BULGE:
9625 // deform vertex array to make the surface have moving bulges
9626 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9627 // rsurface.batchvertex3f_vertexbuffer = NULL;
9628 // rsurface.batchvertex3f_bufferoffset = 0;
9629 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9630 // rsurface.batchnormal3f_vertexbuffer = NULL;
9631 // rsurface.batchnormal3f_bufferoffset = 0;
9632 for (j = 0;j < batchnumvertices;j++)
9634 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9635 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9637 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9638 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9639 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9641 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9642 // rsurface.batchsvector3f_vertexbuffer = NULL;
9643 // rsurface.batchsvector3f_bufferoffset = 0;
9644 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9645 // rsurface.batchtvector3f_vertexbuffer = NULL;
9646 // rsurface.batchtvector3f_bufferoffset = 0;
9647 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);
9651 // deform vertex array
9652 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9653 break; // if wavefunc is a nop, don't make a dynamic vertex array
9654 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9655 VectorScale(deform->parms, scale, waveparms);
9656 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9657 // rsurface.batchvertex3f_vertexbuffer = NULL;
9658 // rsurface.batchvertex3f_bufferoffset = 0;
9659 for (j = 0;j < batchnumvertices;j++)
9660 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9665 // generate texcoords based on the chosen texcoord source
9666 switch(rsurface.texture->tcgen.tcgen)
9669 case Q3TCGEN_TEXTURE:
9671 case Q3TCGEN_LIGHTMAP:
9672 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9673 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9674 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9675 if (rsurface.batchtexcoordlightmap2f)
9676 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9678 case Q3TCGEN_VECTOR:
9679 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9680 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9681 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9682 for (j = 0;j < batchnumvertices;j++)
9684 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9685 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9688 case Q3TCGEN_ENVIRONMENT:
9689 // make environment reflections using a spheremap
9690 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9691 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9692 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9693 for (j = 0;j < batchnumvertices;j++)
9695 // identical to Q3A's method, but executed in worldspace so
9696 // carried models can be shiny too
9698 float viewer[3], d, reflected[3], worldreflected[3];
9700 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9701 // VectorNormalize(viewer);
9703 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9705 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9706 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9707 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9708 // note: this is proportinal to viewer, so we can normalize later
9710 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9711 VectorNormalize(worldreflected);
9713 // note: this sphere map only uses world x and z!
9714 // so positive and negative y will LOOK THE SAME.
9715 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9716 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9720 // the only tcmod that needs software vertex processing is turbulent, so
9721 // check for it here and apply the changes if needed
9722 // and we only support that as the first one
9723 // (handling a mixture of turbulent and other tcmods would be problematic
9724 // without punting it entirely to a software path)
9725 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9727 amplitude = rsurface.texture->tcmods[0].parms[1];
9728 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9729 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9730 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9731 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9732 for (j = 0;j < batchnumvertices;j++)
9734 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);
9735 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9739 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9741 // convert the modified arrays to vertex structs
9742 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9743 // rsurface.batchvertexmeshbuffer = NULL;
9744 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9745 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9746 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9747 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9748 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9749 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9750 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9752 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9754 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9755 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9758 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9759 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9760 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9761 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9762 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9763 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9764 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9765 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9766 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9767 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9769 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9771 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9772 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9778 void RSurf_DrawBatch(void)
9780 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9781 // through the pipeline, killing it earlier in the pipeline would have
9782 // per-surface overhead rather than per-batch overhead, so it's best to
9783 // reject it here, before it hits glDraw.
9784 if (rsurface.batchnumtriangles == 0)
9787 // batch debugging code
9788 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9794 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9795 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9798 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9800 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9802 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9803 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);
9810 if (rsurface.batchmultidraw)
9812 // issue multiple draws rather than copying index data
9813 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9814 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9815 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9816 for (i = 0;i < numsurfaces;)
9818 // combine consecutive surfaces as one draw
9819 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9820 if (surfacelist[j] != surfacelist[k] + 1)
9822 firstvertex = surfacelist[i]->num_firstvertex;
9823 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9824 firsttriangle = surfacelist[i]->num_firsttriangle;
9825 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9826 R_Mesh_Draw(firstvertex, endvertex - firstvertex, firsttriangle, endtriangle - firsttriangle, rsurface.batchelement3i, rsurface.batchelement3i_indexbuffer, rsurface.batchelement3i_bufferoffset, rsurface.batchelement3s, rsurface.batchelement3s_indexbuffer, rsurface.batchelement3s_bufferoffset);
9832 // there is only one consecutive run of index data (may have been combined)
9833 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);
9837 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9839 // pick the closest matching water plane
9840 int planeindex, vertexindex, bestplaneindex = -1;
9844 r_waterstate_waterplane_t *p;
9845 qboolean prepared = false;
9847 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9849 if(p->camera_entity != rsurface.texture->camera_entity)
9854 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9856 if(rsurface.batchnumvertices == 0)
9859 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9861 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9862 d += fabs(PlaneDiff(vert, &p->plane));
9864 if (bestd > d || bestplaneindex < 0)
9867 bestplaneindex = planeindex;
9870 return bestplaneindex;
9871 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9872 // this situation though, as it might be better to render single larger
9873 // batches with useless stuff (backface culled for example) than to
9874 // render multiple smaller batches
9877 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9880 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9881 rsurface.passcolor4f_vertexbuffer = 0;
9882 rsurface.passcolor4f_bufferoffset = 0;
9883 for (i = 0;i < rsurface.batchnumvertices;i++)
9884 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9887 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9894 if (rsurface.passcolor4f)
9896 // generate color arrays
9897 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9898 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9899 rsurface.passcolor4f_vertexbuffer = 0;
9900 rsurface.passcolor4f_bufferoffset = 0;
9901 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)
9903 f = RSurf_FogVertex(v);
9912 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9913 rsurface.passcolor4f_vertexbuffer = 0;
9914 rsurface.passcolor4f_bufferoffset = 0;
9915 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9917 f = RSurf_FogVertex(v);
9926 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9933 if (!rsurface.passcolor4f)
9935 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9936 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9937 rsurface.passcolor4f_vertexbuffer = 0;
9938 rsurface.passcolor4f_bufferoffset = 0;
9939 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)
9941 f = RSurf_FogVertex(v);
9942 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9943 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9944 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9949 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9954 if (!rsurface.passcolor4f)
9956 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9957 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9958 rsurface.passcolor4f_vertexbuffer = 0;
9959 rsurface.passcolor4f_bufferoffset = 0;
9960 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9969 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9974 if (!rsurface.passcolor4f)
9976 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9977 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9978 rsurface.passcolor4f_vertexbuffer = 0;
9979 rsurface.passcolor4f_bufferoffset = 0;
9980 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9982 c2[0] = c[0] + r_refdef.scene.ambient;
9983 c2[1] = c[1] + r_refdef.scene.ambient;
9984 c2[2] = c[2] + r_refdef.scene.ambient;
9989 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9992 rsurface.passcolor4f = NULL;
9993 rsurface.passcolor4f_vertexbuffer = 0;
9994 rsurface.passcolor4f_bufferoffset = 0;
9995 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9996 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9997 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9998 GL_Color(r, g, b, a);
9999 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10003 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10005 // TODO: optimize applyfog && applycolor case
10006 // just apply fog if necessary, and tint the fog color array if necessary
10007 rsurface.passcolor4f = NULL;
10008 rsurface.passcolor4f_vertexbuffer = 0;
10009 rsurface.passcolor4f_bufferoffset = 0;
10010 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10011 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10012 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10013 GL_Color(r, g, b, a);
10017 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10020 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10021 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10022 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10023 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10024 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10025 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10026 GL_Color(r, g, b, a);
10030 static void RSurf_DrawBatch_GL11_ClampColor(void)
10035 if (!rsurface.passcolor4f)
10037 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10039 c2[0] = bound(0.0f, c1[0], 1.0f);
10040 c2[1] = bound(0.0f, c1[1], 1.0f);
10041 c2[2] = bound(0.0f, c1[2], 1.0f);
10042 c2[3] = bound(0.0f, c1[3], 1.0f);
10046 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10056 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10057 rsurface.passcolor4f_vertexbuffer = 0;
10058 rsurface.passcolor4f_bufferoffset = 0;
10059 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)
10061 f = -DotProduct(r_refdef.view.forward, n);
10063 f = f * 0.85 + 0.15; // work around so stuff won't get black
10064 f *= r_refdef.lightmapintensity;
10065 Vector4Set(c, f, f, f, 1);
10069 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10071 RSurf_DrawBatch_GL11_ApplyFakeLight();
10072 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10073 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10074 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10075 GL_Color(r, g, b, a);
10079 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10087 vec3_t ambientcolor;
10088 vec3_t diffusecolor;
10092 VectorCopy(rsurface.modellight_lightdir, lightdir);
10093 f = 0.5f * r_refdef.lightmapintensity;
10094 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10095 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10096 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10097 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10098 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10099 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10101 if (VectorLength2(diffusecolor) > 0)
10103 // q3-style directional shading
10104 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10105 rsurface.passcolor4f_vertexbuffer = 0;
10106 rsurface.passcolor4f_bufferoffset = 0;
10107 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)
10109 if ((f = DotProduct(n, lightdir)) > 0)
10110 VectorMA(ambientcolor, f, diffusecolor, c);
10112 VectorCopy(ambientcolor, c);
10119 *applycolor = false;
10123 *r = ambientcolor[0];
10124 *g = ambientcolor[1];
10125 *b = ambientcolor[2];
10126 rsurface.passcolor4f = NULL;
10127 rsurface.passcolor4f_vertexbuffer = 0;
10128 rsurface.passcolor4f_bufferoffset = 0;
10132 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10134 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10135 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10136 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10137 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10138 GL_Color(r, g, b, a);
10142 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10150 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10151 rsurface.passcolor4f_vertexbuffer = 0;
10152 rsurface.passcolor4f_bufferoffset = 0;
10154 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10156 f = 1 - RSurf_FogVertex(v);
10164 void RSurf_SetupDepthAndCulling(void)
10166 // submodels are biased to avoid z-fighting with world surfaces that they
10167 // may be exactly overlapping (avoids z-fighting artifacts on certain
10168 // doors and things in Quake maps)
10169 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10170 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10171 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10172 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10175 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10177 // transparent sky would be ridiculous
10178 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10180 R_SetupShader_Generic_NoTexture(false, false);
10181 skyrenderlater = true;
10182 RSurf_SetupDepthAndCulling();
10183 GL_DepthMask(true);
10184 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10185 // skymasking on them, and Quake3 never did sky masking (unlike
10186 // software Quake and software Quake2), so disable the sky masking
10187 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10188 // and skymasking also looks very bad when noclipping outside the
10189 // level, so don't use it then either.
10190 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10192 R_Mesh_ResetTextureState();
10193 if (skyrendermasked)
10195 R_SetupShader_DepthOrShadow(false, false);
10196 // depth-only (masking)
10197 GL_ColorMask(0,0,0,0);
10198 // just to make sure that braindead drivers don't draw
10199 // anything despite that colormask...
10200 GL_BlendFunc(GL_ZERO, GL_ONE);
10201 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10202 if (rsurface.batchvertex3fbuffer)
10203 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10205 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10209 R_SetupShader_Generic_NoTexture(false, false);
10211 GL_BlendFunc(GL_ONE, GL_ZERO);
10212 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10213 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10214 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10217 if (skyrendermasked)
10218 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10220 R_Mesh_ResetTextureState();
10221 GL_Color(1, 1, 1, 1);
10224 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10225 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10226 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10228 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10232 // render screenspace normalmap to texture
10233 GL_DepthMask(true);
10234 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10239 // bind lightmap texture
10241 // water/refraction/reflection/camera surfaces have to be handled specially
10242 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10244 int start, end, startplaneindex;
10245 for (start = 0;start < texturenumsurfaces;start = end)
10247 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10248 if(startplaneindex < 0)
10250 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10251 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10255 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10257 // now that we have a batch using the same planeindex, render it
10258 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10260 // render water or distortion background
10261 GL_DepthMask(true);
10262 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10264 // blend surface on top
10265 GL_DepthMask(false);
10266 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10269 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10271 // render surface with reflection texture as input
10272 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10273 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10280 // render surface batch normally
10281 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10282 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);
10286 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10288 // OpenGL 1.3 path - anything not completely ancient
10289 qboolean applycolor;
10292 const texturelayer_t *layer;
10293 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);
10294 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10296 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10299 int layertexrgbscale;
10300 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10302 if (layerindex == 0)
10303 GL_AlphaTest(true);
10306 GL_AlphaTest(false);
10307 GL_DepthFunc(GL_EQUAL);
10310 GL_DepthMask(layer->depthmask && writedepth);
10311 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10312 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10314 layertexrgbscale = 4;
10315 VectorScale(layer->color, 0.25f, layercolor);
10317 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10319 layertexrgbscale = 2;
10320 VectorScale(layer->color, 0.5f, layercolor);
10324 layertexrgbscale = 1;
10325 VectorScale(layer->color, 1.0f, layercolor);
10327 layercolor[3] = layer->color[3];
10328 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10329 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10330 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10331 switch (layer->type)
10333 case TEXTURELAYERTYPE_LITTEXTURE:
10334 // single-pass lightmapped texture with 2x rgbscale
10335 R_Mesh_TexBind(0, r_texture_white);
10336 R_Mesh_TexMatrix(0, NULL);
10337 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10338 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10339 R_Mesh_TexBind(1, layer->texture);
10340 R_Mesh_TexMatrix(1, &layer->texmatrix);
10341 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10342 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10344 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10345 else if (FAKELIGHT_ENABLED)
10346 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10347 else if (rsurface.uselightmaptexture)
10348 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10350 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10352 case TEXTURELAYERTYPE_TEXTURE:
10353 // singletexture unlit texture with transparency support
10354 R_Mesh_TexBind(0, layer->texture);
10355 R_Mesh_TexMatrix(0, &layer->texmatrix);
10356 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10357 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10358 R_Mesh_TexBind(1, 0);
10359 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10360 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10362 case TEXTURELAYERTYPE_FOG:
10363 // singletexture fogging
10364 if (layer->texture)
10366 R_Mesh_TexBind(0, layer->texture);
10367 R_Mesh_TexMatrix(0, &layer->texmatrix);
10368 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10369 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10373 R_Mesh_TexBind(0, 0);
10374 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10376 R_Mesh_TexBind(1, 0);
10377 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10378 // generate a color array for the fog pass
10379 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10380 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10384 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10389 GL_DepthFunc(GL_LEQUAL);
10390 GL_AlphaTest(false);
10394 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10396 // OpenGL 1.1 - crusty old voodoo path
10399 const texturelayer_t *layer;
10400 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);
10401 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10403 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10405 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10407 if (layerindex == 0)
10408 GL_AlphaTest(true);
10411 GL_AlphaTest(false);
10412 GL_DepthFunc(GL_EQUAL);
10415 GL_DepthMask(layer->depthmask && writedepth);
10416 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10417 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10418 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10419 switch (layer->type)
10421 case TEXTURELAYERTYPE_LITTEXTURE:
10422 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10424 // two-pass lit texture with 2x rgbscale
10425 // first the lightmap pass
10426 R_Mesh_TexBind(0, r_texture_white);
10427 R_Mesh_TexMatrix(0, NULL);
10428 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10429 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10430 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10431 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10432 else if (FAKELIGHT_ENABLED)
10433 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10434 else if (rsurface.uselightmaptexture)
10435 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10437 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10438 // then apply the texture to it
10439 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10440 R_Mesh_TexBind(0, layer->texture);
10441 R_Mesh_TexMatrix(0, &layer->texmatrix);
10442 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10443 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10444 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);
10448 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10449 R_Mesh_TexBind(0, layer->texture);
10450 R_Mesh_TexMatrix(0, &layer->texmatrix);
10451 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10452 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10453 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10454 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);
10455 else if (FAKELIGHT_ENABLED)
10456 RSurf_DrawBatch_GL11_FakeLight(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);
10458 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);
10461 case TEXTURELAYERTYPE_TEXTURE:
10462 // singletexture unlit texture with transparency support
10463 R_Mesh_TexBind(0, layer->texture);
10464 R_Mesh_TexMatrix(0, &layer->texmatrix);
10465 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10466 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10467 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);
10469 case TEXTURELAYERTYPE_FOG:
10470 // singletexture fogging
10471 if (layer->texture)
10473 R_Mesh_TexBind(0, layer->texture);
10474 R_Mesh_TexMatrix(0, &layer->texmatrix);
10475 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10476 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10480 R_Mesh_TexBind(0, 0);
10481 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10483 // generate a color array for the fog pass
10484 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10485 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10489 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10492 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10494 GL_DepthFunc(GL_LEQUAL);
10495 GL_AlphaTest(false);
10499 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10503 r_vertexgeneric_t *batchvertex;
10506 // R_Mesh_ResetTextureState();
10507 R_SetupShader_Generic_NoTexture(false, false);
10509 if(rsurface.texture && rsurface.texture->currentskinframe)
10511 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10512 c[3] *= rsurface.texture->currentalpha;
10522 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10524 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10525 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10526 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10529 // brighten it up (as texture value 127 means "unlit")
10530 c[0] *= 2 * r_refdef.view.colorscale;
10531 c[1] *= 2 * r_refdef.view.colorscale;
10532 c[2] *= 2 * r_refdef.view.colorscale;
10534 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10535 c[3] *= r_wateralpha.value;
10537 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10539 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10540 GL_DepthMask(false);
10542 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10544 GL_BlendFunc(GL_ONE, GL_ONE);
10545 GL_DepthMask(false);
10547 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10549 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10550 GL_DepthMask(false);
10552 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10554 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10555 GL_DepthMask(false);
10559 GL_BlendFunc(GL_ONE, GL_ZERO);
10560 GL_DepthMask(writedepth);
10563 if (r_showsurfaces.integer == 3)
10565 rsurface.passcolor4f = NULL;
10567 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10569 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10571 rsurface.passcolor4f = NULL;
10572 rsurface.passcolor4f_vertexbuffer = 0;
10573 rsurface.passcolor4f_bufferoffset = 0;
10575 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10577 qboolean applycolor = true;
10580 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10582 r_refdef.lightmapintensity = 1;
10583 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10584 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10586 else if (FAKELIGHT_ENABLED)
10588 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10590 r_refdef.lightmapintensity = r_fakelight_intensity.value;
10591 RSurf_DrawBatch_GL11_ApplyFakeLight();
10592 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10596 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10598 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10599 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10600 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10603 if(!rsurface.passcolor4f)
10604 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10606 RSurf_DrawBatch_GL11_ApplyAmbient();
10607 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10608 if(r_refdef.fogenabled)
10609 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10610 RSurf_DrawBatch_GL11_ClampColor();
10612 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10613 R_SetupShader_Generic_NoTexture(false, false);
10616 else if (!r_refdef.view.showdebug)
10618 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10619 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10620 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10622 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10623 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10625 R_Mesh_PrepareVertices_Generic_Unlock();
10628 else if (r_showsurfaces.integer == 4)
10630 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10631 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10632 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10634 unsigned char c = (vi << 3) * (1.0f / 256.0f);
10635 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10636 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10638 R_Mesh_PrepareVertices_Generic_Unlock();
10641 else if (r_showsurfaces.integer == 2)
10644 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10645 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10646 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10648 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10649 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10650 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10651 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10652 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10653 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10654 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10656 R_Mesh_PrepareVertices_Generic_Unlock();
10657 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10661 int texturesurfaceindex;
10663 const msurface_t *surface;
10664 float surfacecolor4f[4];
10665 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10666 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10668 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10670 surface = texturesurfacelist[texturesurfaceindex];
10671 k = (int)(((size_t)surface) / sizeof(msurface_t));
10672 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10673 for (j = 0;j < surface->num_vertices;j++)
10675 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10676 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10680 R_Mesh_PrepareVertices_Generic_Unlock();
10685 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10688 RSurf_SetupDepthAndCulling();
10689 if (r_showsurfaces.integer)
10691 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10694 switch (vid.renderpath)
10696 case RENDERPATH_GL20:
10697 case RENDERPATH_D3D9:
10698 case RENDERPATH_D3D10:
10699 case RENDERPATH_D3D11:
10700 case RENDERPATH_SOFT:
10701 case RENDERPATH_GLES2:
10702 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10704 case RENDERPATH_GL13:
10705 case RENDERPATH_GLES1:
10706 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10708 case RENDERPATH_GL11:
10709 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10715 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10718 RSurf_SetupDepthAndCulling();
10719 if (r_showsurfaces.integer)
10721 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10724 switch (vid.renderpath)
10726 case RENDERPATH_GL20:
10727 case RENDERPATH_D3D9:
10728 case RENDERPATH_D3D10:
10729 case RENDERPATH_D3D11:
10730 case RENDERPATH_SOFT:
10731 case RENDERPATH_GLES2:
10732 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10734 case RENDERPATH_GL13:
10735 case RENDERPATH_GLES1:
10736 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10738 case RENDERPATH_GL11:
10739 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10745 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10748 int texturenumsurfaces, endsurface;
10749 texture_t *texture;
10750 const msurface_t *surface;
10751 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10753 // if the model is static it doesn't matter what value we give for
10754 // wantnormals and wanttangents, so this logic uses only rules applicable
10755 // to a model, knowing that they are meaningless otherwise
10756 if (ent == r_refdef.scene.worldentity)
10757 RSurf_ActiveWorldEntity();
10758 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10759 RSurf_ActiveModelEntity(ent, false, false, false);
10762 switch (vid.renderpath)
10764 case RENDERPATH_GL20:
10765 case RENDERPATH_D3D9:
10766 case RENDERPATH_D3D10:
10767 case RENDERPATH_D3D11:
10768 case RENDERPATH_SOFT:
10769 case RENDERPATH_GLES2:
10770 RSurf_ActiveModelEntity(ent, true, true, false);
10772 case RENDERPATH_GL11:
10773 case RENDERPATH_GL13:
10774 case RENDERPATH_GLES1:
10775 RSurf_ActiveModelEntity(ent, true, false, false);
10780 if (r_transparentdepthmasking.integer)
10782 qboolean setup = false;
10783 for (i = 0;i < numsurfaces;i = j)
10786 surface = rsurface.modelsurfaces + surfacelist[i];
10787 texture = surface->texture;
10788 rsurface.texture = R_GetCurrentTexture(texture);
10789 rsurface.lightmaptexture = NULL;
10790 rsurface.deluxemaptexture = NULL;
10791 rsurface.uselightmaptexture = false;
10792 // scan ahead until we find a different texture
10793 endsurface = min(i + 1024, numsurfaces);
10794 texturenumsurfaces = 0;
10795 texturesurfacelist[texturenumsurfaces++] = surface;
10796 for (;j < endsurface;j++)
10798 surface = rsurface.modelsurfaces + surfacelist[j];
10799 if (texture != surface->texture)
10801 texturesurfacelist[texturenumsurfaces++] = surface;
10803 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10805 // render the range of surfaces as depth
10809 GL_ColorMask(0,0,0,0);
10811 GL_DepthTest(true);
10812 GL_BlendFunc(GL_ONE, GL_ZERO);
10813 GL_DepthMask(true);
10814 // R_Mesh_ResetTextureState();
10815 R_SetupShader_DepthOrShadow(false, false);
10817 RSurf_SetupDepthAndCulling();
10818 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10819 if (rsurface.batchvertex3fbuffer)
10820 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10822 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10826 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10829 for (i = 0;i < numsurfaces;i = j)
10832 surface = rsurface.modelsurfaces + surfacelist[i];
10833 texture = surface->texture;
10834 rsurface.texture = R_GetCurrentTexture(texture);
10835 // scan ahead until we find a different texture
10836 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10837 texturenumsurfaces = 0;
10838 texturesurfacelist[texturenumsurfaces++] = surface;
10839 if(FAKELIGHT_ENABLED)
10841 rsurface.lightmaptexture = NULL;
10842 rsurface.deluxemaptexture = NULL;
10843 rsurface.uselightmaptexture = false;
10844 for (;j < endsurface;j++)
10846 surface = rsurface.modelsurfaces + surfacelist[j];
10847 if (texture != surface->texture)
10849 texturesurfacelist[texturenumsurfaces++] = surface;
10854 rsurface.lightmaptexture = surface->lightmaptexture;
10855 rsurface.deluxemaptexture = surface->deluxemaptexture;
10856 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10857 for (;j < endsurface;j++)
10859 surface = rsurface.modelsurfaces + surfacelist[j];
10860 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10862 texturesurfacelist[texturenumsurfaces++] = surface;
10865 // render the range of surfaces
10866 if (ent == r_refdef.scene.worldentity)
10867 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10869 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10871 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10874 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10876 // transparent surfaces get pushed off into the transparent queue
10877 int surfacelistindex;
10878 const msurface_t *surface;
10879 vec3_t tempcenter, center;
10880 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10882 surface = texturesurfacelist[surfacelistindex];
10883 if (r_transparent_sortsurfacesbynearest.integer)
10885 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10886 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10887 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10891 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10892 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10893 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10895 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10896 if (rsurface.entity->transparent_offset) // transparent offset
10898 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10899 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10900 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10902 R_MeshQueue_AddTransparent((rsurface.entity->flags & RENDER_WORLDOBJECT) ? TRANSPARENTSORT_SKY : (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? TRANSPARENTSORT_HUD : rsurface.texture->transparentsort, center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10906 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10908 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10910 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10912 RSurf_SetupDepthAndCulling();
10913 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10914 if (rsurface.batchvertex3fbuffer)
10915 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10917 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10921 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10925 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10928 if (!rsurface.texture->currentnumlayers)
10930 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10931 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10933 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10935 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10936 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10937 else if (!rsurface.texture->currentnumlayers)
10939 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10941 // in the deferred case, transparent surfaces were queued during prepass
10942 if (!r_shadow_usingdeferredprepass)
10943 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10947 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10948 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10953 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10956 texture_t *texture;
10957 R_FrameData_SetMark();
10958 // break the surface list down into batches by texture and use of lightmapping
10959 for (i = 0;i < numsurfaces;i = j)
10962 // texture is the base texture pointer, rsurface.texture is the
10963 // current frame/skin the texture is directing us to use (for example
10964 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10965 // use skin 1 instead)
10966 texture = surfacelist[i]->texture;
10967 rsurface.texture = R_GetCurrentTexture(texture);
10968 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10970 // if this texture is not the kind we want, skip ahead to the next one
10971 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10975 if(FAKELIGHT_ENABLED || depthonly || prepass)
10977 rsurface.lightmaptexture = NULL;
10978 rsurface.deluxemaptexture = NULL;
10979 rsurface.uselightmaptexture = false;
10980 // simply scan ahead until we find a different texture or lightmap state
10981 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10986 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10987 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10988 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10989 // simply scan ahead until we find a different texture or lightmap state
10990 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10993 // render the range of surfaces
10994 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10996 R_FrameData_ReturnToMark();
10999 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11003 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11006 if (!rsurface.texture->currentnumlayers)
11008 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11009 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11011 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11013 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11014 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11015 else if (!rsurface.texture->currentnumlayers)
11017 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11019 // in the deferred case, transparent surfaces were queued during prepass
11020 if (!r_shadow_usingdeferredprepass)
11021 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11025 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11026 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11031 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11034 texture_t *texture;
11035 R_FrameData_SetMark();
11036 // break the surface list down into batches by texture and use of lightmapping
11037 for (i = 0;i < numsurfaces;i = j)
11040 // texture is the base texture pointer, rsurface.texture is the
11041 // current frame/skin the texture is directing us to use (for example
11042 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11043 // use skin 1 instead)
11044 texture = surfacelist[i]->texture;
11045 rsurface.texture = R_GetCurrentTexture(texture);
11046 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11048 // if this texture is not the kind we want, skip ahead to the next one
11049 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11053 if(FAKELIGHT_ENABLED || depthonly || prepass)
11055 rsurface.lightmaptexture = NULL;
11056 rsurface.deluxemaptexture = NULL;
11057 rsurface.uselightmaptexture = false;
11058 // simply scan ahead until we find a different texture or lightmap state
11059 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11064 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11065 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11066 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11067 // simply scan ahead until we find a different texture or lightmap state
11068 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11071 // render the range of surfaces
11072 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11074 R_FrameData_ReturnToMark();
11077 float locboxvertex3f[6*4*3] =
11079 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11080 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11081 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11082 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11083 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11084 1,0,0, 0,0,0, 0,1,0, 1,1,0
11087 unsigned short locboxelements[6*2*3] =
11092 12,13,14, 12,14,15,
11093 16,17,18, 16,18,19,
11097 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11100 cl_locnode_t *loc = (cl_locnode_t *)ent;
11102 float vertex3f[6*4*3];
11104 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11105 GL_DepthMask(false);
11106 GL_DepthRange(0, 1);
11107 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11108 GL_DepthTest(true);
11109 GL_CullFace(GL_NONE);
11110 R_EntityMatrix(&identitymatrix);
11112 // R_Mesh_ResetTextureState();
11114 i = surfacelist[0];
11115 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11116 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11117 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11118 surfacelist[0] < 0 ? 0.5f : 0.125f);
11120 if (VectorCompare(loc->mins, loc->maxs))
11122 VectorSet(size, 2, 2, 2);
11123 VectorMA(loc->mins, -0.5f, size, mins);
11127 VectorCopy(loc->mins, mins);
11128 VectorSubtract(loc->maxs, loc->mins, size);
11131 for (i = 0;i < 6*4*3;)
11132 for (j = 0;j < 3;j++, i++)
11133 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11135 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11136 R_SetupShader_Generic_NoTexture(false, false);
11137 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11140 void R_DrawLocs(void)
11143 cl_locnode_t *loc, *nearestloc;
11145 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11146 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11148 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11149 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11153 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11155 if (decalsystem->decals)
11156 Mem_Free(decalsystem->decals);
11157 memset(decalsystem, 0, sizeof(*decalsystem));
11160 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)
11163 tridecal_t *decals;
11166 // expand or initialize the system
11167 if (decalsystem->maxdecals <= decalsystem->numdecals)
11169 decalsystem_t old = *decalsystem;
11170 qboolean useshortelements;
11171 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11172 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11173 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)));
11174 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11175 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11176 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11177 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11178 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11179 if (decalsystem->numdecals)
11180 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11182 Mem_Free(old.decals);
11183 for (i = 0;i < decalsystem->maxdecals*3;i++)
11184 decalsystem->element3i[i] = i;
11185 if (useshortelements)
11186 for (i = 0;i < decalsystem->maxdecals*3;i++)
11187 decalsystem->element3s[i] = i;
11190 // grab a decal and search for another free slot for the next one
11191 decals = decalsystem->decals;
11192 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11193 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11195 decalsystem->freedecal = i;
11196 if (decalsystem->numdecals <= i)
11197 decalsystem->numdecals = i + 1;
11199 // initialize the decal
11201 decal->triangleindex = triangleindex;
11202 decal->surfaceindex = surfaceindex;
11203 decal->decalsequence = decalsequence;
11204 decal->color4f[0][0] = c0[0];
11205 decal->color4f[0][1] = c0[1];
11206 decal->color4f[0][2] = c0[2];
11207 decal->color4f[0][3] = 1;
11208 decal->color4f[1][0] = c1[0];
11209 decal->color4f[1][1] = c1[1];
11210 decal->color4f[1][2] = c1[2];
11211 decal->color4f[1][3] = 1;
11212 decal->color4f[2][0] = c2[0];
11213 decal->color4f[2][1] = c2[1];
11214 decal->color4f[2][2] = c2[2];
11215 decal->color4f[2][3] = 1;
11216 decal->vertex3f[0][0] = v0[0];
11217 decal->vertex3f[0][1] = v0[1];
11218 decal->vertex3f[0][2] = v0[2];
11219 decal->vertex3f[1][0] = v1[0];
11220 decal->vertex3f[1][1] = v1[1];
11221 decal->vertex3f[1][2] = v1[2];
11222 decal->vertex3f[2][0] = v2[0];
11223 decal->vertex3f[2][1] = v2[1];
11224 decal->vertex3f[2][2] = v2[2];
11225 decal->texcoord2f[0][0] = t0[0];
11226 decal->texcoord2f[0][1] = t0[1];
11227 decal->texcoord2f[1][0] = t1[0];
11228 decal->texcoord2f[1][1] = t1[1];
11229 decal->texcoord2f[2][0] = t2[0];
11230 decal->texcoord2f[2][1] = t2[1];
11231 TriangleNormal(v0, v1, v2, decal->plane);
11232 VectorNormalize(decal->plane);
11233 decal->plane[3] = DotProduct(v0, decal->plane);
11236 extern cvar_t cl_decals_bias;
11237 extern cvar_t cl_decals_models;
11238 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11239 // baseparms, parms, temps
11240 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)
11245 const float *vertex3f;
11246 const float *normal3f;
11248 float points[2][9][3];
11255 e = rsurface.modelelement3i + 3*triangleindex;
11257 vertex3f = rsurface.modelvertex3f;
11258 normal3f = rsurface.modelnormal3f;
11262 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11264 index = 3*e[cornerindex];
11265 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11270 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11272 index = 3*e[cornerindex];
11273 VectorCopy(vertex3f + index, v[cornerindex]);
11278 //TriangleNormal(v[0], v[1], v[2], normal);
11279 //if (DotProduct(normal, localnormal) < 0.0f)
11281 // clip by each of the box planes formed from the projection matrix
11282 // if anything survives, we emit the decal
11283 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]);
11286 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]);
11289 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]);
11292 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]);
11295 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]);
11298 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]);
11301 // some part of the triangle survived, so we have to accept it...
11304 // dynamic always uses the original triangle
11306 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11308 index = 3*e[cornerindex];
11309 VectorCopy(vertex3f + index, v[cornerindex]);
11312 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11314 // convert vertex positions to texcoords
11315 Matrix4x4_Transform(projection, v[cornerindex], temp);
11316 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11317 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11318 // calculate distance fade from the projection origin
11319 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11320 f = bound(0.0f, f, 1.0f);
11321 c[cornerindex][0] = r * f;
11322 c[cornerindex][1] = g * f;
11323 c[cornerindex][2] = b * f;
11324 c[cornerindex][3] = 1.0f;
11325 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11328 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);
11330 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11331 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);
11333 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)
11335 matrix4x4_t projection;
11336 decalsystem_t *decalsystem;
11339 const msurface_t *surface;
11340 const msurface_t *surfaces;
11341 const int *surfacelist;
11342 const texture_t *texture;
11344 int numsurfacelist;
11345 int surfacelistindex;
11348 float localorigin[3];
11349 float localnormal[3];
11350 float localmins[3];
11351 float localmaxs[3];
11354 float planes[6][4];
11357 int bih_triangles_count;
11358 int bih_triangles[256];
11359 int bih_surfaces[256];
11361 decalsystem = &ent->decalsystem;
11362 model = ent->model;
11363 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11365 R_DecalSystem_Reset(&ent->decalsystem);
11369 if (!model->brush.data_leafs && !cl_decals_models.integer)
11371 if (decalsystem->model)
11372 R_DecalSystem_Reset(decalsystem);
11376 if (decalsystem->model != model)
11377 R_DecalSystem_Reset(decalsystem);
11378 decalsystem->model = model;
11380 RSurf_ActiveModelEntity(ent, true, false, false);
11382 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11383 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11384 VectorNormalize(localnormal);
11385 localsize = worldsize*rsurface.inversematrixscale;
11386 localmins[0] = localorigin[0] - localsize;
11387 localmins[1] = localorigin[1] - localsize;
11388 localmins[2] = localorigin[2] - localsize;
11389 localmaxs[0] = localorigin[0] + localsize;
11390 localmaxs[1] = localorigin[1] + localsize;
11391 localmaxs[2] = localorigin[2] + localsize;
11393 //VectorCopy(localnormal, planes[4]);
11394 //VectorVectors(planes[4], planes[2], planes[0]);
11395 AnglesFromVectors(angles, localnormal, NULL, false);
11396 AngleVectors(angles, planes[0], planes[2], planes[4]);
11397 VectorNegate(planes[0], planes[1]);
11398 VectorNegate(planes[2], planes[3]);
11399 VectorNegate(planes[4], planes[5]);
11400 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11401 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11402 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11403 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11404 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11405 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11410 matrix4x4_t forwardprojection;
11411 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11412 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11417 float projectionvector[4][3];
11418 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11419 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11420 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11421 projectionvector[0][0] = planes[0][0] * ilocalsize;
11422 projectionvector[0][1] = planes[1][0] * ilocalsize;
11423 projectionvector[0][2] = planes[2][0] * ilocalsize;
11424 projectionvector[1][0] = planes[0][1] * ilocalsize;
11425 projectionvector[1][1] = planes[1][1] * ilocalsize;
11426 projectionvector[1][2] = planes[2][1] * ilocalsize;
11427 projectionvector[2][0] = planes[0][2] * ilocalsize;
11428 projectionvector[2][1] = planes[1][2] * ilocalsize;
11429 projectionvector[2][2] = planes[2][2] * ilocalsize;
11430 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11431 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11432 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11433 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11437 dynamic = model->surfmesh.isanimated;
11438 numsurfacelist = model->nummodelsurfaces;
11439 surfacelist = model->sortedmodelsurfaces;
11440 surfaces = model->data_surfaces;
11443 bih_triangles_count = -1;
11446 if(model->render_bih.numleafs)
11447 bih = &model->render_bih;
11448 else if(model->collision_bih.numleafs)
11449 bih = &model->collision_bih;
11452 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11453 if(bih_triangles_count == 0)
11455 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11457 if(bih_triangles_count > 0)
11459 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11461 surfaceindex = bih_surfaces[triangleindex];
11462 surface = surfaces + surfaceindex;
11463 texture = surface->texture;
11464 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11466 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11468 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11473 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11475 surfaceindex = surfacelist[surfacelistindex];
11476 surface = surfaces + surfaceindex;
11477 // check cull box first because it rejects more than any other check
11478 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11480 // skip transparent surfaces
11481 texture = surface->texture;
11482 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11484 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11486 numtriangles = surface->num_triangles;
11487 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11488 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11493 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11494 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)
11496 int renderentityindex;
11497 float worldmins[3];
11498 float worldmaxs[3];
11499 entity_render_t *ent;
11501 if (!cl_decals_newsystem.integer)
11504 worldmins[0] = worldorigin[0] - worldsize;
11505 worldmins[1] = worldorigin[1] - worldsize;
11506 worldmins[2] = worldorigin[2] - worldsize;
11507 worldmaxs[0] = worldorigin[0] + worldsize;
11508 worldmaxs[1] = worldorigin[1] + worldsize;
11509 worldmaxs[2] = worldorigin[2] + worldsize;
11511 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11513 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11515 ent = r_refdef.scene.entities[renderentityindex];
11516 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11519 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11523 typedef struct r_decalsystem_splatqueue_s
11525 vec3_t worldorigin;
11526 vec3_t worldnormal;
11532 r_decalsystem_splatqueue_t;
11534 int r_decalsystem_numqueued = 0;
11535 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11537 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)
11539 r_decalsystem_splatqueue_t *queue;
11541 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11544 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11545 VectorCopy(worldorigin, queue->worldorigin);
11546 VectorCopy(worldnormal, queue->worldnormal);
11547 Vector4Set(queue->color, r, g, b, a);
11548 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11549 queue->worldsize = worldsize;
11550 queue->decalsequence = cl.decalsequence++;
11553 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11556 r_decalsystem_splatqueue_t *queue;
11558 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11559 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);
11560 r_decalsystem_numqueued = 0;
11563 extern cvar_t cl_decals_max;
11564 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11567 decalsystem_t *decalsystem = &ent->decalsystem;
11574 if (!decalsystem->numdecals)
11577 if (r_showsurfaces.integer)
11580 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11582 R_DecalSystem_Reset(decalsystem);
11586 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11587 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11589 if (decalsystem->lastupdatetime)
11590 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11593 decalsystem->lastupdatetime = r_refdef.scene.time;
11594 numdecals = decalsystem->numdecals;
11596 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11598 if (decal->color4f[0][3])
11600 decal->lived += frametime;
11601 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11603 memset(decal, 0, sizeof(*decal));
11604 if (decalsystem->freedecal > i)
11605 decalsystem->freedecal = i;
11609 decal = decalsystem->decals;
11610 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11613 // collapse the array by shuffling the tail decals into the gaps
11616 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11617 decalsystem->freedecal++;
11618 if (decalsystem->freedecal == numdecals)
11620 decal[decalsystem->freedecal] = decal[--numdecals];
11623 decalsystem->numdecals = numdecals;
11625 if (numdecals <= 0)
11627 // if there are no decals left, reset decalsystem
11628 R_DecalSystem_Reset(decalsystem);
11632 extern skinframe_t *decalskinframe;
11633 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11636 decalsystem_t *decalsystem = &ent->decalsystem;
11645 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11648 numdecals = decalsystem->numdecals;
11652 if (r_showsurfaces.integer)
11655 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11657 R_DecalSystem_Reset(decalsystem);
11661 // if the model is static it doesn't matter what value we give for
11662 // wantnormals and wanttangents, so this logic uses only rules applicable
11663 // to a model, knowing that they are meaningless otherwise
11664 if (ent == r_refdef.scene.worldentity)
11665 RSurf_ActiveWorldEntity();
11667 RSurf_ActiveModelEntity(ent, false, false, false);
11669 decalsystem->lastupdatetime = r_refdef.scene.time;
11671 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11673 // update vertex positions for animated models
11674 v3f = decalsystem->vertex3f;
11675 c4f = decalsystem->color4f;
11676 t2f = decalsystem->texcoord2f;
11677 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11679 if (!decal->color4f[0][3])
11682 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11686 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11689 // update color values for fading decals
11690 if (decal->lived >= cl_decals_time.value)
11691 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11695 c4f[ 0] = decal->color4f[0][0] * alpha;
11696 c4f[ 1] = decal->color4f[0][1] * alpha;
11697 c4f[ 2] = decal->color4f[0][2] * alpha;
11699 c4f[ 4] = decal->color4f[1][0] * alpha;
11700 c4f[ 5] = decal->color4f[1][1] * alpha;
11701 c4f[ 6] = decal->color4f[1][2] * alpha;
11703 c4f[ 8] = decal->color4f[2][0] * alpha;
11704 c4f[ 9] = decal->color4f[2][1] * alpha;
11705 c4f[10] = decal->color4f[2][2] * alpha;
11708 t2f[0] = decal->texcoord2f[0][0];
11709 t2f[1] = decal->texcoord2f[0][1];
11710 t2f[2] = decal->texcoord2f[1][0];
11711 t2f[3] = decal->texcoord2f[1][1];
11712 t2f[4] = decal->texcoord2f[2][0];
11713 t2f[5] = decal->texcoord2f[2][1];
11715 // update vertex positions for animated models
11716 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11718 e = rsurface.modelelement3i + 3*decal->triangleindex;
11719 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11720 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11721 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11725 VectorCopy(decal->vertex3f[0], v3f);
11726 VectorCopy(decal->vertex3f[1], v3f + 3);
11727 VectorCopy(decal->vertex3f[2], v3f + 6);
11730 if (r_refdef.fogenabled)
11732 alpha = RSurf_FogVertex(v3f);
11733 VectorScale(c4f, alpha, c4f);
11734 alpha = RSurf_FogVertex(v3f + 3);
11735 VectorScale(c4f + 4, alpha, c4f + 4);
11736 alpha = RSurf_FogVertex(v3f + 6);
11737 VectorScale(c4f + 8, alpha, c4f + 8);
11748 r_refdef.stats.drawndecals += numtris;
11750 // now render the decals all at once
11751 // (this assumes they all use one particle font texture!)
11752 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);
11753 // R_Mesh_ResetTextureState();
11754 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11755 GL_DepthMask(false);
11756 GL_DepthRange(0, 1);
11757 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11758 GL_DepthTest(true);
11759 GL_CullFace(GL_NONE);
11760 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11761 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11762 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11766 static void R_DrawModelDecals(void)
11770 // fade faster when there are too many decals
11771 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11772 for (i = 0;i < r_refdef.scene.numentities;i++)
11773 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11775 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11776 for (i = 0;i < r_refdef.scene.numentities;i++)
11777 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11778 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11780 R_DecalSystem_ApplySplatEntitiesQueue();
11782 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11783 for (i = 0;i < r_refdef.scene.numentities;i++)
11784 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11786 r_refdef.stats.totaldecals += numdecals;
11788 if (r_showsurfaces.integer)
11791 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11793 for (i = 0;i < r_refdef.scene.numentities;i++)
11795 if (!r_refdef.viewcache.entityvisible[i])
11797 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11798 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11802 extern cvar_t mod_collision_bih;
11803 static void R_DrawDebugModel(void)
11805 entity_render_t *ent = rsurface.entity;
11806 int i, j, k, l, flagsmask;
11807 const msurface_t *surface;
11808 dp_model_t *model = ent->model;
11811 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11814 if (r_showoverdraw.value > 0)
11816 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11817 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11818 R_SetupShader_Generic_NoTexture(false, false);
11819 GL_DepthTest(false);
11820 GL_DepthMask(false);
11821 GL_DepthRange(0, 1);
11822 GL_BlendFunc(GL_ONE, GL_ONE);
11823 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11825 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11827 rsurface.texture = R_GetCurrentTexture(surface->texture);
11828 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11830 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11831 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11832 if (!rsurface.texture->currentlayers->depthmask)
11833 GL_Color(c, 0, 0, 1.0f);
11834 else if (ent == r_refdef.scene.worldentity)
11835 GL_Color(c, c, c, 1.0f);
11837 GL_Color(0, c, 0, 1.0f);
11838 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11842 rsurface.texture = NULL;
11845 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11847 // R_Mesh_ResetTextureState();
11848 R_SetupShader_Generic_NoTexture(false, false);
11849 GL_DepthRange(0, 1);
11850 GL_DepthTest(!r_showdisabledepthtest.integer);
11851 GL_DepthMask(false);
11852 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11854 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11858 qboolean cullbox = false;
11859 const q3mbrush_t *brush;
11860 const bih_t *bih = &model->collision_bih;
11861 const bih_leaf_t *bihleaf;
11862 float vertex3f[3][3];
11863 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11864 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11866 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11868 switch (bihleaf->type)
11871 brush = model->brush.data_brushes + bihleaf->itemindex;
11872 if (brush->colbrushf && brush->colbrushf->numtriangles)
11874 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);
11875 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11876 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11879 case BIH_COLLISIONTRIANGLE:
11880 triangleindex = bihleaf->itemindex;
11881 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11882 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11883 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11884 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);
11885 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11886 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11888 case BIH_RENDERTRIANGLE:
11889 triangleindex = bihleaf->itemindex;
11890 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11891 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11892 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11893 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);
11894 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11895 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11901 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11904 if (r_showtris.integer && qglPolygonMode)
11906 if (r_showdisabledepthtest.integer)
11908 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11909 GL_DepthMask(false);
11913 GL_BlendFunc(GL_ONE, GL_ZERO);
11914 GL_DepthMask(true);
11916 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11917 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11919 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11921 rsurface.texture = R_GetCurrentTexture(surface->texture);
11922 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11924 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11925 if (!rsurface.texture->currentlayers->depthmask)
11926 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11927 else if (ent == r_refdef.scene.worldentity)
11928 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11930 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11931 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11935 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11936 rsurface.texture = NULL;
11939 if (r_shownormals.value != 0 && qglBegin)
11941 if (r_showdisabledepthtest.integer)
11943 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11944 GL_DepthMask(false);
11948 GL_BlendFunc(GL_ONE, GL_ZERO);
11949 GL_DepthMask(true);
11951 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11953 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11955 rsurface.texture = R_GetCurrentTexture(surface->texture);
11956 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11958 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11959 qglBegin(GL_LINES);
11960 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11962 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11964 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11965 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11966 qglVertex3f(v[0], v[1], v[2]);
11967 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11968 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11969 qglVertex3f(v[0], v[1], v[2]);
11972 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11974 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11976 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11977 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11978 qglVertex3f(v[0], v[1], v[2]);
11979 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11980 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11981 qglVertex3f(v[0], v[1], v[2]);
11984 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11986 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11988 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11989 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11990 qglVertex3f(v[0], v[1], v[2]);
11991 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11992 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11993 qglVertex3f(v[0], v[1], v[2]);
11996 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11998 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12000 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12001 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12002 qglVertex3f(v[0], v[1], v[2]);
12003 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12004 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12005 qglVertex3f(v[0], v[1], v[2]);
12012 rsurface.texture = NULL;
12017 int r_maxsurfacelist = 0;
12018 const msurface_t **r_surfacelist = NULL;
12019 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12021 int i, j, endj, flagsmask;
12022 dp_model_t *model = r_refdef.scene.worldmodel;
12023 msurface_t *surfaces;
12024 unsigned char *update;
12025 int numsurfacelist = 0;
12029 if (r_maxsurfacelist < model->num_surfaces)
12031 r_maxsurfacelist = model->num_surfaces;
12033 Mem_Free((msurface_t**)r_surfacelist);
12034 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12037 RSurf_ActiveWorldEntity();
12039 surfaces = model->data_surfaces;
12040 update = model->brushq1.lightmapupdateflags;
12042 // update light styles on this submodel
12043 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12045 model_brush_lightstyleinfo_t *style;
12046 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12048 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12050 int *list = style->surfacelist;
12051 style->value = r_refdef.scene.lightstylevalue[style->style];
12052 for (j = 0;j < style->numsurfaces;j++)
12053 update[list[j]] = true;
12058 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12062 R_DrawDebugModel();
12063 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12067 rsurface.lightmaptexture = NULL;
12068 rsurface.deluxemaptexture = NULL;
12069 rsurface.uselightmaptexture = false;
12070 rsurface.texture = NULL;
12071 rsurface.rtlight = NULL;
12072 numsurfacelist = 0;
12073 // add visible surfaces to draw list
12074 for (i = 0;i < model->nummodelsurfaces;i++)
12076 j = model->sortedmodelsurfaces[i];
12077 if (r_refdef.viewcache.world_surfacevisible[j])
12078 r_surfacelist[numsurfacelist++] = surfaces + j;
12080 // update lightmaps if needed
12081 if (model->brushq1.firstrender)
12083 model->brushq1.firstrender = false;
12084 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12086 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12090 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12091 if (r_refdef.viewcache.world_surfacevisible[j])
12093 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12095 // don't do anything if there were no surfaces
12096 if (!numsurfacelist)
12098 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12101 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12103 // add to stats if desired
12104 if (r_speeds.integer && !skysurfaces && !depthonly)
12106 r_refdef.stats.world_surfaces += numsurfacelist;
12107 for (j = 0;j < numsurfacelist;j++)
12108 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
12111 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12114 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12116 int i, j, endj, flagsmask;
12117 dp_model_t *model = ent->model;
12118 msurface_t *surfaces;
12119 unsigned char *update;
12120 int numsurfacelist = 0;
12124 if (r_maxsurfacelist < model->num_surfaces)
12126 r_maxsurfacelist = model->num_surfaces;
12128 Mem_Free((msurface_t **)r_surfacelist);
12129 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12132 // if the model is static it doesn't matter what value we give for
12133 // wantnormals and wanttangents, so this logic uses only rules applicable
12134 // to a model, knowing that they are meaningless otherwise
12135 if (ent == r_refdef.scene.worldentity)
12136 RSurf_ActiveWorldEntity();
12137 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12138 RSurf_ActiveModelEntity(ent, false, false, false);
12140 RSurf_ActiveModelEntity(ent, true, true, true);
12141 else if (depthonly)
12143 switch (vid.renderpath)
12145 case RENDERPATH_GL20:
12146 case RENDERPATH_D3D9:
12147 case RENDERPATH_D3D10:
12148 case RENDERPATH_D3D11:
12149 case RENDERPATH_SOFT:
12150 case RENDERPATH_GLES2:
12151 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12153 case RENDERPATH_GL11:
12154 case RENDERPATH_GL13:
12155 case RENDERPATH_GLES1:
12156 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12162 switch (vid.renderpath)
12164 case RENDERPATH_GL20:
12165 case RENDERPATH_D3D9:
12166 case RENDERPATH_D3D10:
12167 case RENDERPATH_D3D11:
12168 case RENDERPATH_SOFT:
12169 case RENDERPATH_GLES2:
12170 RSurf_ActiveModelEntity(ent, true, true, false);
12172 case RENDERPATH_GL11:
12173 case RENDERPATH_GL13:
12174 case RENDERPATH_GLES1:
12175 RSurf_ActiveModelEntity(ent, true, false, false);
12180 surfaces = model->data_surfaces;
12181 update = model->brushq1.lightmapupdateflags;
12183 // update light styles
12184 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12186 model_brush_lightstyleinfo_t *style;
12187 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12189 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12191 int *list = style->surfacelist;
12192 style->value = r_refdef.scene.lightstylevalue[style->style];
12193 for (j = 0;j < style->numsurfaces;j++)
12194 update[list[j]] = true;
12199 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12203 R_DrawDebugModel();
12204 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12208 rsurface.lightmaptexture = NULL;
12209 rsurface.deluxemaptexture = NULL;
12210 rsurface.uselightmaptexture = false;
12211 rsurface.texture = NULL;
12212 rsurface.rtlight = NULL;
12213 numsurfacelist = 0;
12214 // add visible surfaces to draw list
12215 for (i = 0;i < model->nummodelsurfaces;i++)
12216 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12217 // don't do anything if there were no surfaces
12218 if (!numsurfacelist)
12220 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12223 // update lightmaps if needed
12227 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12232 R_BuildLightMap(ent, surfaces + j);
12237 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12239 // add to stats if desired
12240 if (r_speeds.integer && !skysurfaces && !depthonly)
12242 r_refdef.stats.entities_surfaces += numsurfacelist;
12243 for (j = 0;j < numsurfacelist;j++)
12244 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12247 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12250 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12252 static texture_t texture;
12253 static msurface_t surface;
12254 const msurface_t *surfacelist = &surface;
12256 // fake enough texture and surface state to render this geometry
12258 texture.update_lastrenderframe = -1; // regenerate this texture
12259 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12260 texture.currentskinframe = skinframe;
12261 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12262 texture.offsetmapping = OFFSETMAPPING_OFF;
12263 texture.offsetscale = 1;
12264 texture.specularscalemod = 1;
12265 texture.specularpowermod = 1;
12266 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12267 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12268 // JUST GREP FOR "specularscalemod = 1".
12270 surface.texture = &texture;
12271 surface.num_triangles = numtriangles;
12272 surface.num_firsttriangle = firsttriangle;
12273 surface.num_vertices = numvertices;
12274 surface.num_firstvertex = firstvertex;
12277 rsurface.texture = R_GetCurrentTexture(surface.texture);
12278 rsurface.lightmaptexture = NULL;
12279 rsurface.deluxemaptexture = NULL;
12280 rsurface.uselightmaptexture = false;
12281 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12284 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)
12286 static msurface_t surface;
12287 const msurface_t *surfacelist = &surface;
12289 // fake enough texture and surface state to render this geometry
12290 surface.texture = texture;
12291 surface.num_triangles = numtriangles;
12292 surface.num_firsttriangle = firsttriangle;
12293 surface.num_vertices = numvertices;
12294 surface.num_firstvertex = firstvertex;
12297 rsurface.texture = R_GetCurrentTexture(surface.texture);
12298 rsurface.lightmaptexture = NULL;
12299 rsurface.deluxemaptexture = NULL;
12300 rsurface.uselightmaptexture = false;
12301 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);