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;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
40 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
44 mempool_t *r_main_mempool;
45 rtexturepool_t *r_main_texturepool;
47 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
49 static qboolean r_loadnormalmap;
50 static qboolean r_loadgloss;
52 static qboolean r_loaddds;
53 static qboolean r_savedds;
54 static qboolean r_gpuskeletal;
61 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!"};
62 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!"};
63 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
64 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
65 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)"};
66 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
67 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"};
68 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"};
69 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"};
70 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"};
71 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"};
72 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"};
74 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
75 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"};
76 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
77 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)"};
78 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
80 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"};
81 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
82 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
83 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
84 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
85 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
86 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
87 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"};
88 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"};
89 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"};
90 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
91 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
92 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)"};
93 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
94 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
95 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"};
96 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"};
97 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
98 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"};
99 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"};
100 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"};
101 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
102 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
103 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
104 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
105 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
106 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
107 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
108 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)"};
109 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)"};
110 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
111 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
112 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
113 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
114 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
116 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
117 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
118 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
120 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
121 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
122 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
123 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."};
124 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
125 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
126 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
127 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."};
128 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
129 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
130 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
131 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."};
132 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
133 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"};
134 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"};
135 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
136 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
137 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
138 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
139 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
140 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"};
141 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
142 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
143 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
144 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
145 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
147 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
148 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
149 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
150 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
151 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
152 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
153 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
154 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
156 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)"};
157 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"};
159 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
160 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
161 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
163 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"};
164 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"};
165 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"};
166 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
167 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
168 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"};
169 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)"};
170 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)"};
171 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
173 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
174 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)"};
175 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
176 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)"};
177 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
178 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)"};
179 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)"};
180 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
181 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"};
182 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."};
183 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
184 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)"};
185 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)"};
186 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)"};
187 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)"};
188 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)"};
189 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)"};
190 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)"};
191 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)"};
193 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)"};
194 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
195 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
196 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"};
197 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
198 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
199 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
200 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"};
201 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"};
202 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)"};
204 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
205 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
206 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
207 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
209 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
210 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
212 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
213 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
214 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
215 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
216 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
217 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
219 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
220 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
221 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
222 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
223 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
224 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
225 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
226 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
227 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
228 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
230 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"};
232 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"};
234 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
236 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
238 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)"};
239 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)"};
240 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
241 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
243 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
244 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"};
246 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."};
248 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)"};
249 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
251 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
252 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
253 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
254 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
257 extern cvar_t v_glslgamma;
258 extern cvar_t v_glslgamma_2d;
260 extern qboolean v_flipped_state;
262 r_framebufferstate_t r_fb;
264 /// shadow volume bsp struct with automatically growing nodes buffer
267 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
269 rtexture_t *r_texture_blanknormalmap;
270 rtexture_t *r_texture_white;
271 rtexture_t *r_texture_grey128;
272 rtexture_t *r_texture_black;
273 rtexture_t *r_texture_notexture;
274 rtexture_t *r_texture_whitecube;
275 rtexture_t *r_texture_normalizationcube;
276 rtexture_t *r_texture_fogattenuation;
277 rtexture_t *r_texture_fogheighttexture;
278 rtexture_t *r_texture_gammaramps;
279 unsigned int r_texture_gammaramps_serial;
280 //rtexture_t *r_texture_fogintensity;
281 rtexture_t *r_texture_reflectcube;
283 // TODO: hash lookups?
284 typedef struct cubemapinfo_s
291 int r_texture_numcubemaps;
292 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
294 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
295 unsigned int r_numqueries;
296 unsigned int r_maxqueries;
298 typedef struct r_qwskincache_s
300 char name[MAX_QPATH];
301 skinframe_t *skinframe;
305 static r_qwskincache_t *r_qwskincache;
306 static int r_qwskincache_size;
308 /// vertex coordinates for a quad that covers the screen exactly
309 extern const float r_screenvertex3f[12];
310 extern const float r_d3dscreenvertex3f[12];
311 const float r_screenvertex3f[12] =
318 const float r_d3dscreenvertex3f[12] =
326 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
329 for (i = 0;i < verts;i++)
340 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
343 for (i = 0;i < verts;i++)
353 // FIXME: move this to client?
356 if (gamemode == GAME_NEHAHRA)
358 Cvar_Set("gl_fogenable", "0");
359 Cvar_Set("gl_fogdensity", "0.2");
360 Cvar_Set("gl_fogred", "0.3");
361 Cvar_Set("gl_foggreen", "0.3");
362 Cvar_Set("gl_fogblue", "0.3");
364 r_refdef.fog_density = 0;
365 r_refdef.fog_red = 0;
366 r_refdef.fog_green = 0;
367 r_refdef.fog_blue = 0;
368 r_refdef.fog_alpha = 1;
369 r_refdef.fog_start = 0;
370 r_refdef.fog_end = 16384;
371 r_refdef.fog_height = 1<<30;
372 r_refdef.fog_fadedepth = 128;
373 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
376 static void R_BuildBlankTextures(void)
378 unsigned char data[4];
379 data[2] = 128; // normal X
380 data[1] = 128; // normal Y
381 data[0] = 255; // normal Z
382 data[3] = 255; // height
383 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 static void R_BuildNoTexture(void)
404 unsigned char pix[16][16][4];
405 // this makes a light grey/dark grey checkerboard texture
406 for (y = 0;y < 16;y++)
408 for (x = 0;x < 16;x++)
410 if ((y < 8) ^ (x < 8))
426 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildWhiteCube(void)
431 unsigned char data[6*1*1*4];
432 memset(data, 255, sizeof(data));
433 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
436 static void R_BuildNormalizationCube(void)
440 vec_t s, t, intensity;
443 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
444 for (side = 0;side < 6;side++)
446 for (y = 0;y < NORMSIZE;y++)
448 for (x = 0;x < NORMSIZE;x++)
450 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
486 intensity = 127.0f / sqrt(DotProduct(v, v));
487 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
488 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
489 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
490 data[((side*64+y)*64+x)*4+3] = 255;
494 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
498 static void R_BuildFogTexture(void)
502 unsigned char data1[FOGWIDTH][4];
503 //unsigned char data2[FOGWIDTH][4];
506 r_refdef.fogmasktable_start = r_refdef.fog_start;
507 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
508 r_refdef.fogmasktable_range = r_refdef.fogrange;
509 r_refdef.fogmasktable_density = r_refdef.fog_density;
511 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
512 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
514 d = (x * r - r_refdef.fogmasktable_start);
515 if(developer_extra.integer)
516 Con_DPrintf("%f ", d);
518 if (r_fog_exp2.integer)
519 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
521 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
522 if(developer_extra.integer)
523 Con_DPrintf(" : %f ", alpha);
524 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
525 if(developer_extra.integer)
526 Con_DPrintf(" = %f\n", alpha);
527 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
530 for (x = 0;x < FOGWIDTH;x++)
532 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537 //data2[x][0] = 255 - b;
538 //data2[x][1] = 255 - b;
539 //data2[x][2] = 255 - b;
542 if (r_texture_fogattenuation)
544 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
550 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
554 static void R_BuildFogHeightTexture(void)
556 unsigned char *inpixels;
564 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
565 if (r_refdef.fogheighttexturename[0])
566 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
569 r_refdef.fog_height_tablesize = 0;
570 if (r_texture_fogheighttexture)
571 R_FreeTexture(r_texture_fogheighttexture);
572 r_texture_fogheighttexture = NULL;
573 if (r_refdef.fog_height_table2d)
574 Mem_Free(r_refdef.fog_height_table2d);
575 r_refdef.fog_height_table2d = NULL;
576 if (r_refdef.fog_height_table1d)
577 Mem_Free(r_refdef.fog_height_table1d);
578 r_refdef.fog_height_table1d = NULL;
582 r_refdef.fog_height_tablesize = size;
583 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
584 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
585 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
587 // LordHavoc: now the magic - what is that table2d for? it is a cooked
588 // average fog color table accounting for every fog layer between a point
589 // and the camera. (Note: attenuation is handled separately!)
590 for (y = 0;y < size;y++)
592 for (x = 0;x < size;x++)
598 for (j = x;j <= y;j++)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 for (j = x;j >= y;j--)
608 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
614 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
615 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
616 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
619 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
622 //=======================================================================================================================================================
624 static const char *builtinshaderstrings[] =
626 #include "shader_glsl.h"
630 const char *builtinhlslshaderstrings[] =
632 #include "shader_hlsl.h"
636 char *glslshaderstring = NULL;
637 char *hlslshaderstring = NULL;
639 //=======================================================================================================================================================
641 typedef struct shaderpermutationinfo_s
646 shaderpermutationinfo_t;
648 typedef struct shadermodeinfo_s
650 const char *filename;
656 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
657 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
659 {"#define USEDIFFUSE\n", " diffuse"},
660 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
661 {"#define USEVIEWTINT\n", " viewtint"},
662 {"#define USECOLORMAPPING\n", " colormapping"},
663 {"#define USESATURATION\n", " saturation"},
664 {"#define USEFOGINSIDE\n", " foginside"},
665 {"#define USEFOGOUTSIDE\n", " fogoutside"},
666 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
667 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
668 {"#define USEGAMMARAMPS\n", " gammaramps"},
669 {"#define USECUBEFILTER\n", " cubefilter"},
670 {"#define USEGLOW\n", " glow"},
671 {"#define USEBLOOM\n", " bloom"},
672 {"#define USESPECULAR\n", " specular"},
673 {"#define USEPOSTPROCESSING\n", " postprocessing"},
674 {"#define USEREFLECTION\n", " reflection"},
675 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
676 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
677 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
678 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
679 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
680 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
681 {"#define USEALPHAKILL\n", " alphakill"},
682 {"#define USEREFLECTCUBE\n", " reflectcube"},
683 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
684 {"#define USEBOUNCEGRID\n", " bouncegrid"},
685 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
686 {"#define USETRIPPY\n", " trippy"},
687 {"#define USEDEPTHRGB\n", " depthrgb"},
688 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
689 {"#define USESKELETAL\n", " skeletal"},
690 {"#define USEOCCLUDE\n", " occlude"}
693 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
694 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
696 {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
697 {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
698 {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
699 {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
700 {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
701 {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
702 {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
703 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
704 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
705 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
706 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
707 {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
708 {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
709 {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
710 {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
711 {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
712 {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
715 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
717 {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
718 {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
719 {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
720 {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
721 {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
722 {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
723 {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
724 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
725 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
726 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
727 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
728 {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
729 {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
730 {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
731 {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
732 {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
733 {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
736 struct r_glsl_permutation_s;
737 typedef struct r_glsl_permutation_s
740 struct r_glsl_permutation_s *hashnext;
742 unsigned int permutation;
744 /// indicates if we have tried compiling this permutation already
746 /// 0 if compilation failed
748 // texture units assigned to each detected uniform
749 int tex_Texture_First;
750 int tex_Texture_Second;
751 int tex_Texture_GammaRamps;
752 int tex_Texture_Normal;
753 int tex_Texture_Color;
754 int tex_Texture_Gloss;
755 int tex_Texture_Glow;
756 int tex_Texture_SecondaryNormal;
757 int tex_Texture_SecondaryColor;
758 int tex_Texture_SecondaryGloss;
759 int tex_Texture_SecondaryGlow;
760 int tex_Texture_Pants;
761 int tex_Texture_Shirt;
762 int tex_Texture_FogHeightTexture;
763 int tex_Texture_FogMask;
764 int tex_Texture_Lightmap;
765 int tex_Texture_Deluxemap;
766 int tex_Texture_Attenuation;
767 int tex_Texture_Cube;
768 int tex_Texture_Refraction;
769 int tex_Texture_Reflection;
770 int tex_Texture_ShadowMap2D;
771 int tex_Texture_CubeProjection;
772 int tex_Texture_ScreenNormalMap;
773 int tex_Texture_ScreenDiffuse;
774 int tex_Texture_ScreenSpecular;
775 int tex_Texture_ReflectMask;
776 int tex_Texture_ReflectCube;
777 int tex_Texture_BounceGrid;
778 /// locations of detected uniforms in program object, or -1 if not found
779 int loc_Texture_First;
780 int loc_Texture_Second;
781 int loc_Texture_GammaRamps;
782 int loc_Texture_Normal;
783 int loc_Texture_Color;
784 int loc_Texture_Gloss;
785 int loc_Texture_Glow;
786 int loc_Texture_SecondaryNormal;
787 int loc_Texture_SecondaryColor;
788 int loc_Texture_SecondaryGloss;
789 int loc_Texture_SecondaryGlow;
790 int loc_Texture_Pants;
791 int loc_Texture_Shirt;
792 int loc_Texture_FogHeightTexture;
793 int loc_Texture_FogMask;
794 int loc_Texture_Lightmap;
795 int loc_Texture_Deluxemap;
796 int loc_Texture_Attenuation;
797 int loc_Texture_Cube;
798 int loc_Texture_Refraction;
799 int loc_Texture_Reflection;
800 int loc_Texture_ShadowMap2D;
801 int loc_Texture_CubeProjection;
802 int loc_Texture_ScreenNormalMap;
803 int loc_Texture_ScreenDiffuse;
804 int loc_Texture_ScreenSpecular;
805 int loc_Texture_ReflectMask;
806 int loc_Texture_ReflectCube;
807 int loc_Texture_BounceGrid;
809 int loc_BloomBlur_Parameters;
811 int loc_Color_Ambient;
812 int loc_Color_Diffuse;
813 int loc_Color_Specular;
817 int loc_DeferredColor_Ambient;
818 int loc_DeferredColor_Diffuse;
819 int loc_DeferredColor_Specular;
820 int loc_DeferredMod_Diffuse;
821 int loc_DeferredMod_Specular;
822 int loc_DistortScaleRefractReflect;
825 int loc_FogHeightFade;
827 int loc_FogPlaneViewDist;
828 int loc_FogRangeRecip;
831 int loc_LightPosition;
832 int loc_OffsetMapping_ScaleSteps;
833 int loc_OffsetMapping_LodDistance;
834 int loc_OffsetMapping_Bias;
836 int loc_ReflectColor;
837 int loc_ReflectFactor;
838 int loc_ReflectOffset;
839 int loc_RefractColor;
841 int loc_ScreenCenterRefractReflect;
842 int loc_ScreenScaleRefractReflect;
843 int loc_ScreenToDepth;
844 int loc_ShadowMap_Parameters;
845 int loc_ShadowMap_TextureScale;
846 int loc_SpecularPower;
847 int loc_Skeletal_Transform12;
852 int loc_ViewTintColor;
854 int loc_ModelToLight;
856 int loc_BackgroundTexMatrix;
857 int loc_ModelViewProjectionMatrix;
858 int loc_ModelViewMatrix;
859 int loc_PixelToScreenTexCoord;
860 int loc_ModelToReflectCube;
861 int loc_ShadowMapMatrix;
862 int loc_BloomColorSubtract;
863 int loc_NormalmapScrollBlend;
864 int loc_BounceGridMatrix;
865 int loc_BounceGridIntensity;
866 /// uniform block bindings
867 int ubibind_Skeletal_Transform12_UniformBlock;
868 /// uniform block indices
869 int ubiloc_Skeletal_Transform12_UniformBlock;
871 r_glsl_permutation_t;
873 #define SHADERPERMUTATION_HASHSIZE 256
876 // non-degradable "lightweight" shader parameters to keep the permutations simpler
877 // these can NOT degrade! only use for simple stuff
880 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
881 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
882 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
883 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
884 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
885 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
886 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
887 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
888 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
889 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
890 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
891 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
892 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
893 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
895 #define SHADERSTATICPARMS_COUNT 14
897 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
898 static int shaderstaticparms_count = 0;
900 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
901 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
903 extern qboolean r_shadow_shadowmapsampler;
904 extern int r_shadow_shadowmappcf;
905 qboolean R_CompileShader_CheckStaticParms(void)
907 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
908 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
909 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
912 if (r_glsl_saturation_redcompensate.integer)
913 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
914 if (r_glsl_vertextextureblend_usebothalphas.integer)
915 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
916 if (r_shadow_glossexact.integer)
917 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
918 if (r_glsl_postprocess.integer)
920 if (r_glsl_postprocess_uservec1_enable.integer)
921 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
922 if (r_glsl_postprocess_uservec2_enable.integer)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
924 if (r_glsl_postprocess_uservec3_enable.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
926 if (r_glsl_postprocess_uservec4_enable.integer)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
930 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
931 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
932 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
934 if (r_shadow_shadowmapsampler)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
936 if (r_shadow_shadowmappcf > 1)
937 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
938 else if (r_shadow_shadowmappcf)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
940 if (r_celshading.integer)
941 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
942 if (r_celoutlines.integer)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
945 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
948 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
949 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
950 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
952 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
953 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
955 shaderstaticparms_count = 0;
958 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
959 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
960 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
961 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
962 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
963 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
964 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
965 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
966 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
967 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
968 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
969 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
974 /// information about each possible shader permutation
975 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
976 /// currently selected permutation
977 r_glsl_permutation_t *r_glsl_permutation;
978 /// storage for permutations linked in the hash table
979 memexpandablearray_t r_glsl_permutationarray;
981 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
983 //unsigned int hashdepth = 0;
984 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
985 r_glsl_permutation_t *p;
986 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
988 if (p->mode == mode && p->permutation == permutation)
990 //if (hashdepth > 10)
991 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
996 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
998 p->permutation = permutation;
999 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1000 r_glsl_permutationhash[mode][hashindex] = p;
1001 //if (hashdepth > 10)
1002 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1006 static char *R_ShaderStrCat(const char **strings)
1009 const char **p = strings;
1012 for (p = strings;(t = *p);p++)
1015 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1017 for (p = strings;(t = *p);p++)
1027 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1030 if (!filename || !filename[0])
1032 // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1033 if (!strcmp(filename, "glsl/default.glsl"))
1036 return R_ShaderStrCat(builtinshaderstrings);
1037 if (!glslshaderstring)
1039 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1040 if (glslshaderstring)
1041 Con_DPrintf("Loading shaders from file %s...\n", filename);
1043 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1045 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1046 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1047 return shaderstring;
1049 if (!strcmp(filename, "hlsl/default.hlsl"))
1052 return R_ShaderStrCat(builtinhlslshaderstrings);
1053 if (!hlslshaderstring)
1055 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1056 if (hlslshaderstring)
1057 Con_DPrintf("Loading shaders from file %s...\n", filename);
1059 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1061 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1062 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1063 return shaderstring;
1065 // we don't have builtin strings for any other files
1068 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1071 if (printfromdisknotice)
1072 Con_DPrintf("from disk %s... ", filename);
1073 return shaderstring;
1075 return shaderstring;
1078 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1083 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1085 char permutationname[256];
1086 int vertstrings_count = 0;
1087 int geomstrings_count = 0;
1088 int fragstrings_count = 0;
1089 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1091 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1098 permutationname[0] = 0;
1099 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1101 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1103 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1104 if(vid.support.glshaderversion >= 140)
1106 vertstrings_list[vertstrings_count++] = "#version 140\n";
1107 geomstrings_list[geomstrings_count++] = "#version 140\n";
1108 fragstrings_list[fragstrings_count++] = "#version 140\n";
1109 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1110 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1111 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1113 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1114 else if(vid.support.glshaderversion >= 130)
1116 vertstrings_list[vertstrings_count++] = "#version 130\n";
1117 geomstrings_list[geomstrings_count++] = "#version 130\n";
1118 fragstrings_list[fragstrings_count++] = "#version 130\n";
1119 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1120 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1121 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1124 // the first pretext is which type of shader to compile as
1125 // (later these will all be bound together as a program object)
1126 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1127 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1128 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1130 // the second pretext is the mode (for example a light source)
1131 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1132 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1133 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1134 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1136 // now add all the permutation pretexts
1137 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1139 if (permutation & (1<<i))
1141 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1142 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1143 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1144 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1148 // keep line numbers correct
1149 vertstrings_list[vertstrings_count++] = "\n";
1150 geomstrings_list[geomstrings_count++] = "\n";
1151 fragstrings_list[fragstrings_count++] = "\n";
1156 R_CompileShader_AddStaticParms(mode, permutation);
1157 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1158 vertstrings_count += shaderstaticparms_count;
1159 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1160 geomstrings_count += shaderstaticparms_count;
1161 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162 fragstrings_count += shaderstaticparms_count;
1164 // now append the shader text itself
1165 vertstrings_list[vertstrings_count++] = sourcestring;
1166 geomstrings_list[geomstrings_count++] = sourcestring;
1167 fragstrings_list[fragstrings_count++] = sourcestring;
1169 // compile the shader program
1170 if (vertstrings_count + geomstrings_count + fragstrings_count)
1171 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1175 qglUseProgram(p->program);CHECKGLERROR
1176 // look up all the uniform variable names we care about, so we don't
1177 // have to look them up every time we set them
1182 GLint activeuniformindex = 0;
1183 GLint numactiveuniforms = 0;
1184 char uniformname[128];
1185 GLsizei uniformnamelength = 0;
1186 GLint uniformsize = 0;
1187 GLenum uniformtype = 0;
1188 memset(uniformname, 0, sizeof(uniformname));
1189 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1190 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1191 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1193 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1194 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1199 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1200 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1201 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1202 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1203 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1204 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1205 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1206 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1207 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1208 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1209 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1210 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1211 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1212 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1213 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1214 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1215 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1216 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1217 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1218 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1219 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1220 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1221 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1222 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1223 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1224 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1225 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1226 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1227 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1228 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1229 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1230 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1231 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1232 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1233 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1234 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1235 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1236 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1237 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1238 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1239 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1240 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1241 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1242 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1243 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1244 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1245 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1246 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1247 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1248 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1249 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1250 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1251 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1252 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1253 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1254 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1255 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1256 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1257 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1258 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1259 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1260 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1261 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1262 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1263 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1264 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1265 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1266 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1267 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1268 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1269 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1270 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1271 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1272 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1273 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1274 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1275 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1276 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1277 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1278 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1279 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1280 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1281 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1282 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1283 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1284 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1285 // initialize the samplers to refer to the texture units we use
1286 p->tex_Texture_First = -1;
1287 p->tex_Texture_Second = -1;
1288 p->tex_Texture_GammaRamps = -1;
1289 p->tex_Texture_Normal = -1;
1290 p->tex_Texture_Color = -1;
1291 p->tex_Texture_Gloss = -1;
1292 p->tex_Texture_Glow = -1;
1293 p->tex_Texture_SecondaryNormal = -1;
1294 p->tex_Texture_SecondaryColor = -1;
1295 p->tex_Texture_SecondaryGloss = -1;
1296 p->tex_Texture_SecondaryGlow = -1;
1297 p->tex_Texture_Pants = -1;
1298 p->tex_Texture_Shirt = -1;
1299 p->tex_Texture_FogHeightTexture = -1;
1300 p->tex_Texture_FogMask = -1;
1301 p->tex_Texture_Lightmap = -1;
1302 p->tex_Texture_Deluxemap = -1;
1303 p->tex_Texture_Attenuation = -1;
1304 p->tex_Texture_Cube = -1;
1305 p->tex_Texture_Refraction = -1;
1306 p->tex_Texture_Reflection = -1;
1307 p->tex_Texture_ShadowMap2D = -1;
1308 p->tex_Texture_CubeProjection = -1;
1309 p->tex_Texture_ScreenNormalMap = -1;
1310 p->tex_Texture_ScreenDiffuse = -1;
1311 p->tex_Texture_ScreenSpecular = -1;
1312 p->tex_Texture_ReflectMask = -1;
1313 p->tex_Texture_ReflectCube = -1;
1314 p->tex_Texture_BounceGrid = -1;
1315 // bind the texture samplers in use
1317 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1318 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1319 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1320 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1321 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1322 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1323 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1324 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1325 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1326 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1327 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1328 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1329 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1330 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1331 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1332 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1333 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1334 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1335 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1336 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1337 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1338 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1339 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1340 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1341 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1342 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1343 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1344 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1345 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1346 // get the uniform block indices so we can bind them
1347 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1348 if (vid.support.arb_uniform_buffer_object)
1349 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1352 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1353 // clear the uniform block bindings
1354 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1355 // bind the uniform blocks in use
1357 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1358 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1360 // we're done compiling and setting up the shader, at least until it is used
1362 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1365 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1369 Mem_Free(sourcestring);
1372 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1374 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1375 if (r_glsl_permutation != perm)
1377 r_glsl_permutation = perm;
1378 if (!r_glsl_permutation->program)
1380 if (!r_glsl_permutation->compiled)
1382 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1383 R_GLSL_CompilePermutation(perm, mode, permutation);
1385 if (!r_glsl_permutation->program)
1387 // remove features until we find a valid permutation
1389 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1391 // reduce i more quickly whenever it would not remove any bits
1392 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1393 if (!(permutation & j))
1396 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1397 if (!r_glsl_permutation->compiled)
1398 R_GLSL_CompilePermutation(perm, mode, permutation);
1399 if (r_glsl_permutation->program)
1402 if (i >= SHADERPERMUTATION_COUNT)
1404 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1405 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1406 qglUseProgram(0);CHECKGLERROR
1407 return; // no bit left to clear, entire mode is broken
1412 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1414 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1415 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1416 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1424 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1425 extern D3DCAPS9 vid_d3d9caps;
1428 struct r_hlsl_permutation_s;
1429 typedef struct r_hlsl_permutation_s
1431 /// hash lookup data
1432 struct r_hlsl_permutation_s *hashnext;
1434 unsigned int permutation;
1436 /// indicates if we have tried compiling this permutation already
1438 /// NULL if compilation failed
1439 IDirect3DVertexShader9 *vertexshader;
1440 IDirect3DPixelShader9 *pixelshader;
1442 r_hlsl_permutation_t;
1444 typedef enum D3DVSREGISTER_e
1446 D3DVSREGISTER_TexMatrix = 0, // float4x4
1447 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1448 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1449 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1450 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1451 D3DVSREGISTER_ModelToLight = 20, // float4x4
1452 D3DVSREGISTER_EyePosition = 24,
1453 D3DVSREGISTER_FogPlane = 25,
1454 D3DVSREGISTER_LightDir = 26,
1455 D3DVSREGISTER_LightPosition = 27,
1459 typedef enum D3DPSREGISTER_e
1461 D3DPSREGISTER_Alpha = 0,
1462 D3DPSREGISTER_BloomBlur_Parameters = 1,
1463 D3DPSREGISTER_ClientTime = 2,
1464 D3DPSREGISTER_Color_Ambient = 3,
1465 D3DPSREGISTER_Color_Diffuse = 4,
1466 D3DPSREGISTER_Color_Specular = 5,
1467 D3DPSREGISTER_Color_Glow = 6,
1468 D3DPSREGISTER_Color_Pants = 7,
1469 D3DPSREGISTER_Color_Shirt = 8,
1470 D3DPSREGISTER_DeferredColor_Ambient = 9,
1471 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1472 D3DPSREGISTER_DeferredColor_Specular = 11,
1473 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1474 D3DPSREGISTER_DeferredMod_Specular = 13,
1475 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1476 D3DPSREGISTER_EyePosition = 15, // unused
1477 D3DPSREGISTER_FogColor = 16,
1478 D3DPSREGISTER_FogHeightFade = 17,
1479 D3DPSREGISTER_FogPlane = 18,
1480 D3DPSREGISTER_FogPlaneViewDist = 19,
1481 D3DPSREGISTER_FogRangeRecip = 20,
1482 D3DPSREGISTER_LightColor = 21,
1483 D3DPSREGISTER_LightDir = 22, // unused
1484 D3DPSREGISTER_LightPosition = 23,
1485 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1486 D3DPSREGISTER_PixelSize = 25,
1487 D3DPSREGISTER_ReflectColor = 26,
1488 D3DPSREGISTER_ReflectFactor = 27,
1489 D3DPSREGISTER_ReflectOffset = 28,
1490 D3DPSREGISTER_RefractColor = 29,
1491 D3DPSREGISTER_Saturation = 30,
1492 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1493 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1494 D3DPSREGISTER_ScreenToDepth = 33,
1495 D3DPSREGISTER_ShadowMap_Parameters = 34,
1496 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1497 D3DPSREGISTER_SpecularPower = 36,
1498 D3DPSREGISTER_UserVec1 = 37,
1499 D3DPSREGISTER_UserVec2 = 38,
1500 D3DPSREGISTER_UserVec3 = 39,
1501 D3DPSREGISTER_UserVec4 = 40,
1502 D3DPSREGISTER_ViewTintColor = 41,
1503 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1504 D3DPSREGISTER_BloomColorSubtract = 43,
1505 D3DPSREGISTER_ViewToLight = 44, // float4x4
1506 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1507 D3DPSREGISTER_NormalmapScrollBlend = 52,
1508 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1509 D3DPSREGISTER_OffsetMapping_Bias = 54,
1514 /// information about each possible shader permutation
1515 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1516 /// currently selected permutation
1517 r_hlsl_permutation_t *r_hlsl_permutation;
1518 /// storage for permutations linked in the hash table
1519 memexpandablearray_t r_hlsl_permutationarray;
1521 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1523 //unsigned int hashdepth = 0;
1524 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1525 r_hlsl_permutation_t *p;
1526 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1528 if (p->mode == mode && p->permutation == permutation)
1530 //if (hashdepth > 10)
1531 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1536 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1538 p->permutation = permutation;
1539 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1540 r_hlsl_permutationhash[mode][hashindex] = p;
1541 //if (hashdepth > 10)
1542 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1547 //#include <d3dx9shader.h>
1548 //#include <d3dx9mesh.h>
1550 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1552 DWORD *vsbin = NULL;
1553 DWORD *psbin = NULL;
1554 fs_offset_t vsbinsize;
1555 fs_offset_t psbinsize;
1556 // IDirect3DVertexShader9 *vs = NULL;
1557 // IDirect3DPixelShader9 *ps = NULL;
1558 ID3DXBuffer *vslog = NULL;
1559 ID3DXBuffer *vsbuffer = NULL;
1560 ID3DXConstantTable *vsconstanttable = NULL;
1561 ID3DXBuffer *pslog = NULL;
1562 ID3DXBuffer *psbuffer = NULL;
1563 ID3DXConstantTable *psconstanttable = NULL;
1566 char temp[MAX_INPUTLINE];
1567 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1569 qboolean debugshader = gl_paranoid.integer != 0;
1570 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1571 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1574 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1575 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1577 if ((!vsbin && vertstring) || (!psbin && fragstring))
1579 const char* dllnames_d3dx9 [] =
1603 dllhandle_t d3dx9_dll = NULL;
1604 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1605 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1606 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1607 dllfunction_t d3dx9_dllfuncs[] =
1609 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1610 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1611 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1614 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1615 #ifndef ID3DXBuffer_GetBufferPointer
1616 #if !defined(__cplusplus) || defined(CINTERFACE)
1617 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1618 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1619 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1621 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1622 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1623 #define ID3DXBuffer_Release(p) (p)->Release()
1626 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1628 DWORD shaderflags = 0;
1630 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1631 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1632 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1633 if (vertstring && vertstring[0])
1637 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1638 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1641 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1644 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1645 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1646 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1647 ID3DXBuffer_Release(vsbuffer);
1651 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1652 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1653 ID3DXBuffer_Release(vslog);
1656 if (fragstring && fragstring[0])
1660 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1661 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1664 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1667 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1668 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1669 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1670 ID3DXBuffer_Release(psbuffer);
1674 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1675 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1676 ID3DXBuffer_Release(pslog);
1679 Sys_UnloadLibrary(&d3dx9_dll);
1682 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1686 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1687 if (FAILED(vsresult))
1688 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1689 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1690 if (FAILED(psresult))
1691 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1693 // free the shader data
1694 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1695 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1698 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1701 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1702 int vertstring_length = 0;
1703 int geomstring_length = 0;
1704 int fragstring_length = 0;
1707 char *vertstring, *geomstring, *fragstring;
1708 char permutationname[256];
1709 char cachename[256];
1710 int vertstrings_count = 0;
1711 int geomstrings_count = 0;
1712 int fragstrings_count = 0;
1713 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1714 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1715 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1720 p->vertexshader = NULL;
1721 p->pixelshader = NULL;
1723 permutationname[0] = 0;
1725 sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1727 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1728 strlcat(cachename, "hlsl/", sizeof(cachename));
1730 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1731 vertstrings_count = 0;
1732 geomstrings_count = 0;
1733 fragstrings_count = 0;
1734 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1735 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1736 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1738 // the first pretext is which type of shader to compile as
1739 // (later these will all be bound together as a program object)
1740 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1741 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1742 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1744 // the second pretext is the mode (for example a light source)
1745 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1746 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1747 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1748 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1749 strlcat(cachename, modeinfo->name, sizeof(cachename));
1751 // now add all the permutation pretexts
1752 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1754 if (permutation & (1<<i))
1756 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1757 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1758 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1759 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1760 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1764 // keep line numbers correct
1765 vertstrings_list[vertstrings_count++] = "\n";
1766 geomstrings_list[geomstrings_count++] = "\n";
1767 fragstrings_list[fragstrings_count++] = "\n";
1772 R_CompileShader_AddStaticParms(mode, permutation);
1773 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1774 vertstrings_count += shaderstaticparms_count;
1775 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1776 geomstrings_count += shaderstaticparms_count;
1777 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778 fragstrings_count += shaderstaticparms_count;
1780 // replace spaces in the cachename with _ characters
1781 for (i = 0;cachename[i];i++)
1782 if (cachename[i] == ' ')
1785 // now append the shader text itself
1786 vertstrings_list[vertstrings_count++] = sourcestring;
1787 geomstrings_list[geomstrings_count++] = sourcestring;
1788 fragstrings_list[fragstrings_count++] = sourcestring;
1790 vertstring_length = 0;
1791 for (i = 0;i < vertstrings_count;i++)
1792 vertstring_length += (int)strlen(vertstrings_list[i]);
1793 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1794 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1795 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1797 geomstring_length = 0;
1798 for (i = 0;i < geomstrings_count;i++)
1799 geomstring_length += (int)strlen(geomstrings_list[i]);
1800 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1801 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1802 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1804 fragstring_length = 0;
1805 for (i = 0;i < fragstrings_count;i++)
1806 fragstring_length += (int)strlen(fragstrings_list[i]);
1807 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1808 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1809 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1811 // try to load the cached shader, or generate one
1812 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1814 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1815 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1817 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1821 Mem_Free(vertstring);
1823 Mem_Free(geomstring);
1825 Mem_Free(fragstring);
1827 Mem_Free(sourcestring);
1830 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1831 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1832 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);}
1833 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);}
1834 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);}
1835 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);}
1837 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1838 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1839 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);}
1840 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);}
1841 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);}
1842 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);}
1844 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1846 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1847 if (r_hlsl_permutation != perm)
1849 r_hlsl_permutation = perm;
1850 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1852 if (!r_hlsl_permutation->compiled)
1853 R_HLSL_CompilePermutation(perm, mode, permutation);
1854 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1856 // remove features until we find a valid permutation
1858 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1860 // reduce i more quickly whenever it would not remove any bits
1861 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1862 if (!(permutation & j))
1865 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1866 if (!r_hlsl_permutation->compiled)
1867 R_HLSL_CompilePermutation(perm, mode, permutation);
1868 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1871 if (i >= SHADERPERMUTATION_COUNT)
1873 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1874 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1875 return; // no bit left to clear, entire mode is broken
1879 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1880 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1882 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1883 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1884 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1888 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1890 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1891 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1892 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1893 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1896 void R_GLSL_Restart_f(void)
1898 unsigned int i, limit;
1899 if (glslshaderstring)
1900 Mem_Free(glslshaderstring);
1901 glslshaderstring = NULL;
1902 if (hlslshaderstring)
1903 Mem_Free(hlslshaderstring);
1904 hlslshaderstring = NULL;
1905 switch(vid.renderpath)
1907 case RENDERPATH_D3D9:
1910 r_hlsl_permutation_t *p;
1911 r_hlsl_permutation = NULL;
1912 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1913 for (i = 0;i < limit;i++)
1915 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1917 if (p->vertexshader)
1918 IDirect3DVertexShader9_Release(p->vertexshader);
1920 IDirect3DPixelShader9_Release(p->pixelshader);
1921 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1924 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1928 case RENDERPATH_D3D10:
1929 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931 case RENDERPATH_D3D11:
1932 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934 case RENDERPATH_GL20:
1935 case RENDERPATH_GLES2:
1937 r_glsl_permutation_t *p;
1938 r_glsl_permutation = NULL;
1939 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1940 for (i = 0;i < limit;i++)
1942 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1944 GL_Backend_FreeProgram(p->program);
1945 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1948 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1951 case RENDERPATH_GL11:
1952 case RENDERPATH_GL13:
1953 case RENDERPATH_GLES1:
1955 case RENDERPATH_SOFT:
1960 static void R_GLSL_DumpShader_f(void)
1962 int i, language, mode, dupe;
1964 shadermodeinfo_t *modeinfo;
1967 for (language = 0;language < 2;language++)
1969 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1970 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1972 // don't dump the same file multiple times (most or all shaders come from the same file)
1973 for (dupe = mode - 1;dupe >= 0;dupe--)
1974 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1978 text = R_GetShaderText(modeinfo[mode].filename, false, true);
1981 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1984 FS_Print(file, "/* The engine may define the following macros:\n");
1985 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1986 for (i = 0;i < SHADERMODE_COUNT;i++)
1987 FS_Print(file, modeinfo[i].pretext);
1988 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1989 FS_Print(file, shaderpermutationinfo[i].pretext);
1990 FS_Print(file, "*/\n");
1991 FS_Print(file, text);
1993 Con_Printf("%s written\n", modeinfo[mode].filename);
1996 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2002 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2004 unsigned int permutation = 0;
2005 if (r_trippy.integer && !notrippy)
2006 permutation |= SHADERPERMUTATION_TRIPPY;
2007 permutation |= SHADERPERMUTATION_VIEWTINT;
2009 permutation |= SHADERPERMUTATION_DIFFUSE;
2011 permutation |= SHADERPERMUTATION_SPECULAR;
2012 if (texturemode == GL_MODULATE)
2013 permutation |= SHADERPERMUTATION_COLORMAPPING;
2014 else if (texturemode == GL_ADD)
2015 permutation |= SHADERPERMUTATION_GLOW;
2016 else if (texturemode == GL_DECAL)
2017 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2018 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2019 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2020 if (suppresstexalpha)
2021 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2023 texturemode = GL_MODULATE;
2024 if (vid.allowalphatocoverage)
2025 GL_AlphaToCoverage(false);
2026 switch (vid.renderpath)
2028 case RENDERPATH_D3D9:
2030 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2031 R_Mesh_TexBind(GL20TU_FIRST , first );
2032 R_Mesh_TexBind(GL20TU_SECOND, second);
2033 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2034 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2037 case RENDERPATH_D3D10:
2038 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040 case RENDERPATH_D3D11:
2041 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043 case RENDERPATH_GL20:
2044 case RENDERPATH_GLES2:
2045 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2046 if (r_glsl_permutation->tex_Texture_First >= 0)
2047 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2048 if (r_glsl_permutation->tex_Texture_Second >= 0)
2049 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2050 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2051 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2053 case RENDERPATH_GL13:
2054 case RENDERPATH_GLES1:
2055 R_Mesh_TexBind(0, first );
2056 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2057 R_Mesh_TexMatrix(0, NULL);
2058 R_Mesh_TexBind(1, second);
2061 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2062 R_Mesh_TexMatrix(1, NULL);
2065 case RENDERPATH_GL11:
2066 R_Mesh_TexBind(0, first );
2067 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2068 R_Mesh_TexMatrix(0, NULL);
2070 case RENDERPATH_SOFT:
2071 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2072 R_Mesh_TexBind(GL20TU_FIRST , first );
2073 R_Mesh_TexBind(GL20TU_SECOND, second);
2078 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2080 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2083 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2085 unsigned int permutation = 0;
2086 if (r_trippy.integer && !notrippy)
2087 permutation |= SHADERPERMUTATION_TRIPPY;
2089 permutation |= SHADERPERMUTATION_DEPTHRGB;
2091 permutation |= SHADERPERMUTATION_SKELETAL;
2093 if (vid.allowalphatocoverage)
2094 GL_AlphaToCoverage(false);
2095 switch (vid.renderpath)
2097 case RENDERPATH_D3D9:
2099 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2102 case RENDERPATH_D3D10:
2103 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2105 case RENDERPATH_D3D11:
2106 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2108 case RENDERPATH_GL20:
2109 case RENDERPATH_GLES2:
2110 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2111 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2112 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2115 case RENDERPATH_GL13:
2116 case RENDERPATH_GLES1:
2117 R_Mesh_TexBind(0, 0);
2118 R_Mesh_TexBind(1, 0);
2120 case RENDERPATH_GL11:
2121 R_Mesh_TexBind(0, 0);
2123 case RENDERPATH_SOFT:
2124 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129 extern qboolean r_shadow_usingdeferredprepass;
2130 extern rtexture_t *r_shadow_attenuationgradienttexture;
2131 extern rtexture_t *r_shadow_attenuation2dtexture;
2132 extern rtexture_t *r_shadow_attenuation3dtexture;
2133 extern qboolean r_shadow_usingshadowmap2d;
2134 extern qboolean r_shadow_usingshadowmaportho;
2135 extern float r_shadow_shadowmap_texturescale[2];
2136 extern float r_shadow_shadowmap_parameters[4];
2137 extern qboolean r_shadow_shadowmapvsdct;
2138 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2139 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2140 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2141 extern matrix4x4_t r_shadow_shadowmapmatrix;
2142 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2143 extern int r_shadow_prepass_width;
2144 extern int r_shadow_prepass_height;
2145 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2146 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2147 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2148 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2150 #define BLENDFUNC_ALLOWS_COLORMOD 1
2151 #define BLENDFUNC_ALLOWS_FOG 2
2152 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2153 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2154 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2155 static int R_BlendFuncFlags(int src, int dst)
2159 // a blendfunc allows colormod if:
2160 // a) it can never keep the destination pixel invariant, or
2161 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2162 // this is to prevent unintended side effects from colormod
2164 // a blendfunc allows fog if:
2165 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2166 // this is to prevent unintended side effects from fog
2168 // these checks are the output of fogeval.pl
2170 r |= BLENDFUNC_ALLOWS_COLORMOD;
2171 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2172 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2174 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2175 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2176 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2179 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2180 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2181 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2183 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2184 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2185 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2187 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2190 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2191 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196 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)
2198 // select a permutation of the lighting shader appropriate to this
2199 // combination of texture, entity, light source, and fogging, only use the
2200 // minimum features necessary to avoid wasting rendering time in the
2201 // fragment shader on features that are not being used
2202 unsigned int permutation = 0;
2203 unsigned int mode = 0;
2205 static float dummy_colormod[3] = {1, 1, 1};
2206 float *colormod = rsurface.colormod;
2208 matrix4x4_t tempmatrix;
2209 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2210 if (r_trippy.integer && !notrippy)
2211 permutation |= SHADERPERMUTATION_TRIPPY;
2212 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2213 permutation |= SHADERPERMUTATION_ALPHAKILL;
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2215 permutation |= SHADERPERMUTATION_OCCLUDE;
2216 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2217 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2218 if (rsurfacepass == RSURFPASS_BACKGROUND)
2220 // distorted background
2221 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2223 mode = SHADERMODE_WATER;
2224 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2225 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2226 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2228 // this is the right thing to do for wateralpha
2229 GL_BlendFunc(GL_ONE, GL_ZERO);
2230 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2234 // this is the right thing to do for entity alpha
2235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2236 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2239 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2241 mode = SHADERMODE_REFRACTION;
2242 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2243 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2244 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2245 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249 mode = SHADERMODE_GENERIC;
2250 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2251 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2252 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2254 if (vid.allowalphatocoverage)
2255 GL_AlphaToCoverage(false);
2257 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2259 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2261 switch(rsurface.texture->offsetmapping)
2263 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2264 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2265 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266 case OFFSETMAPPING_OFF: break;
2269 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271 // normalmap (deferred prepass), may use alpha test on diffuse
2272 mode = SHADERMODE_DEFERREDGEOMETRY;
2273 GL_BlendFunc(GL_ONE, GL_ZERO);
2274 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2275 if (vid.allowalphatocoverage)
2276 GL_AlphaToCoverage(false);
2278 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2280 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2282 switch(rsurface.texture->offsetmapping)
2284 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287 case OFFSETMAPPING_OFF: break;
2290 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2293 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2295 mode = SHADERMODE_LIGHTSOURCE;
2296 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2297 permutation |= SHADERPERMUTATION_CUBEFILTER;
2298 if (diffusescale > 0)
2299 permutation |= SHADERPERMUTATION_DIFFUSE;
2300 if (specularscale > 0)
2301 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2302 if (r_refdef.fogenabled)
2303 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2304 if (rsurface.texture->colormapping)
2305 permutation |= SHADERPERMUTATION_COLORMAPPING;
2306 if (r_shadow_usingshadowmap2d)
2308 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2309 if(r_shadow_shadowmapvsdct)
2310 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2312 if (r_shadow_shadowmap2ddepthbuffer)
2313 permutation |= SHADERPERMUTATION_DEPTHRGB;
2315 if (rsurface.texture->reflectmasktexture)
2316 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2317 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2318 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2319 if (vid.allowalphatocoverage)
2320 GL_AlphaToCoverage(false);
2322 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2324 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2326 switch(rsurface.texture->offsetmapping)
2328 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2329 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2330 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2331 case OFFSETMAPPING_OFF: break;
2334 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2335 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2336 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2337 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2338 // unshaded geometry (fullbright or ambient model lighting)
2339 mode = SHADERMODE_FLATCOLOR;
2340 ambientscale = diffusescale = specularscale = 0;
2341 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2342 permutation |= SHADERPERMUTATION_GLOW;
2343 if (r_refdef.fogenabled)
2344 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2345 if (rsurface.texture->colormapping)
2346 permutation |= SHADERPERMUTATION_COLORMAPPING;
2347 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2349 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2350 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2352 if (r_shadow_shadowmap2ddepthbuffer)
2353 permutation |= SHADERPERMUTATION_DEPTHRGB;
2355 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2356 permutation |= SHADERPERMUTATION_REFLECTION;
2357 if (rsurface.texture->reflectmasktexture)
2358 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2359 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2360 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2361 // when using alphatocoverage, we don't need alphakill
2362 if (vid.allowalphatocoverage)
2364 if (r_transparent_alphatocoverage.integer)
2366 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2367 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2370 GL_AlphaToCoverage(false);
2373 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2375 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2377 switch(rsurface.texture->offsetmapping)
2379 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2380 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2381 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2382 case OFFSETMAPPING_OFF: break;
2385 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2386 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2387 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2388 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2389 // directional model lighting
2390 mode = SHADERMODE_LIGHTDIRECTION;
2391 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2392 permutation |= SHADERPERMUTATION_GLOW;
2393 permutation |= SHADERPERMUTATION_DIFFUSE;
2394 if (specularscale > 0)
2395 permutation |= SHADERPERMUTATION_SPECULAR;
2396 if (r_refdef.fogenabled)
2397 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2398 if (rsurface.texture->colormapping)
2399 permutation |= SHADERPERMUTATION_COLORMAPPING;
2400 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2402 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2403 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2405 if (r_shadow_shadowmap2ddepthbuffer)
2406 permutation |= SHADERPERMUTATION_DEPTHRGB;
2408 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2409 permutation |= SHADERPERMUTATION_REFLECTION;
2410 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2411 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2412 if (rsurface.texture->reflectmasktexture)
2413 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2414 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2416 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417 if (r_shadow_bouncegriddirectional)
2418 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2420 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422 // when using alphatocoverage, we don't need alphakill
2423 if (vid.allowalphatocoverage)
2425 if (r_transparent_alphatocoverage.integer)
2427 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2428 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2431 GL_AlphaToCoverage(false);
2434 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2436 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2438 switch(rsurface.texture->offsetmapping)
2440 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2441 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2442 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2443 case OFFSETMAPPING_OFF: break;
2446 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2447 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2449 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2450 // ambient model lighting
2451 mode = SHADERMODE_LIGHTDIRECTION;
2452 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2453 permutation |= SHADERPERMUTATION_GLOW;
2454 if (r_refdef.fogenabled)
2455 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2456 if (rsurface.texture->colormapping)
2457 permutation |= SHADERPERMUTATION_COLORMAPPING;
2458 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2460 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2461 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2463 if (r_shadow_shadowmap2ddepthbuffer)
2464 permutation |= SHADERPERMUTATION_DEPTHRGB;
2466 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2467 permutation |= SHADERPERMUTATION_REFLECTION;
2468 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2469 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2470 if (rsurface.texture->reflectmasktexture)
2471 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2472 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2474 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2475 if (r_shadow_bouncegriddirectional)
2476 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2478 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2479 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2480 // when using alphatocoverage, we don't need alphakill
2481 if (vid.allowalphatocoverage)
2483 if (r_transparent_alphatocoverage.integer)
2485 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2486 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2489 GL_AlphaToCoverage(false);
2494 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2496 switch(rsurface.texture->offsetmapping)
2498 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2499 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2500 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2501 case OFFSETMAPPING_OFF: break;
2504 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2505 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2506 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2507 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2509 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2510 permutation |= SHADERPERMUTATION_GLOW;
2511 if (r_refdef.fogenabled)
2512 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2513 if (rsurface.texture->colormapping)
2514 permutation |= SHADERPERMUTATION_COLORMAPPING;
2515 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2517 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2518 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2520 if (r_shadow_shadowmap2ddepthbuffer)
2521 permutation |= SHADERPERMUTATION_DEPTHRGB;
2523 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2524 permutation |= SHADERPERMUTATION_REFLECTION;
2525 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2526 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2527 if (rsurface.texture->reflectmasktexture)
2528 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2529 if (FAKELIGHT_ENABLED)
2531 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2532 mode = SHADERMODE_FAKELIGHT;
2533 permutation |= SHADERPERMUTATION_DIFFUSE;
2534 if (specularscale > 0)
2535 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2537 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2539 // deluxemapping (light direction texture)
2540 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2541 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2543 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2544 permutation |= SHADERPERMUTATION_DIFFUSE;
2545 if (specularscale > 0)
2546 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2548 else if (r_glsl_deluxemapping.integer >= 2)
2550 // fake deluxemapping (uniform light direction in tangentspace)
2551 if (rsurface.uselightmaptexture)
2552 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2554 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2555 permutation |= SHADERPERMUTATION_DIFFUSE;
2556 if (specularscale > 0)
2557 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2559 else if (rsurface.uselightmaptexture)
2561 // ordinary lightmapping (q1bsp, q3bsp)
2562 mode = SHADERMODE_LIGHTMAP;
2566 // ordinary vertex coloring (q3bsp)
2567 mode = SHADERMODE_VERTEXCOLOR;
2569 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2571 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2572 if (r_shadow_bouncegriddirectional)
2573 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2575 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2576 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2577 // when using alphatocoverage, we don't need alphakill
2578 if (vid.allowalphatocoverage)
2580 if (r_transparent_alphatocoverage.integer)
2582 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2583 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2586 GL_AlphaToCoverage(false);
2589 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2590 colormod = dummy_colormod;
2591 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2592 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2593 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2594 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2595 switch(vid.renderpath)
2597 case RENDERPATH_D3D9:
2599 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);
2600 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2601 R_SetupShader_SetPermutationHLSL(mode, permutation);
2602 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2603 if (mode == SHADERMODE_LIGHTSOURCE)
2605 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2606 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2610 if (mode == SHADERMODE_LIGHTDIRECTION)
2612 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2615 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2616 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2617 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2618 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2619 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2621 if (mode == SHADERMODE_LIGHTSOURCE)
2623 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2624 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2625 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2626 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2627 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2629 // additive passes are only darkened by fog, not tinted
2630 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2631 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2635 if (mode == SHADERMODE_FLATCOLOR)
2637 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2639 else if (mode == SHADERMODE_LIGHTDIRECTION)
2641 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]);
2642 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2643 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);
2644 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2645 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2646 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2647 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2651 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2652 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2653 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);
2654 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2655 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2657 // additive passes are only darkened by fog, not tinted
2658 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2659 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2661 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2662 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);
2663 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2664 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2665 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2666 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2667 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2668 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2669 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2670 if (mode == SHADERMODE_WATER)
2671 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2673 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2674 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2675 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2676 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));
2677 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2678 if (rsurface.texture->pantstexture)
2679 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2681 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2682 if (rsurface.texture->shirttexture)
2683 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2685 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2686 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2687 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2688 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2689 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2690 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2691 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2692 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2693 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2694 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2696 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2697 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2698 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2699 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2701 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2702 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2703 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2704 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2705 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2706 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2707 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2708 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2709 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2710 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2711 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2712 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2713 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2714 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2715 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2716 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2717 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2718 if (rsurfacepass == RSURFPASS_BACKGROUND)
2720 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2721 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2722 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2726 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2728 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2729 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2730 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2731 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2733 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2734 if (rsurface.rtlight)
2736 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2737 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2742 case RENDERPATH_D3D10:
2743 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2745 case RENDERPATH_D3D11:
2746 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2748 case RENDERPATH_GL20:
2749 case RENDERPATH_GLES2:
2750 if (!vid.useinterleavedarrays)
2752 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);
2753 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2754 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2755 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2756 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2757 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2758 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2759 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2760 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2761 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2762 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2766 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);
2767 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2769 // this has to be after RSurf_PrepareVerticesForBatch
2770 if (rsurface.batchskeletaltransform3x4buffer)
2771 permutation |= SHADERPERMUTATION_SKELETAL;
2772 R_SetupShader_SetPermutationGLSL(mode, permutation);
2773 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2774 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2776 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2777 if (mode == SHADERMODE_LIGHTSOURCE)
2779 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2780 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2781 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2782 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2783 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2784 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);
2786 // additive passes are only darkened by fog, not tinted
2787 if (r_glsl_permutation->loc_FogColor >= 0)
2788 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2789 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);
2793 if (mode == SHADERMODE_FLATCOLOR)
2795 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2797 else if (mode == SHADERMODE_LIGHTDIRECTION)
2799 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]);
2800 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]);
2801 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);
2802 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2803 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2804 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]);
2805 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]);
2809 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]);
2810 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]);
2811 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);
2812 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2813 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2815 // additive passes are only darkened by fog, not tinted
2816 if (r_glsl_permutation->loc_FogColor >= 0)
2818 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2819 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2821 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2823 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);
2824 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]);
2825 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]);
2826 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]);
2827 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]);
2828 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2829 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2830 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);
2831 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]);
2833 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2834 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2835 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2836 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]);
2837 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]);
2839 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2840 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));
2841 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2842 if (r_glsl_permutation->loc_Color_Pants >= 0)
2844 if (rsurface.texture->pantstexture)
2845 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2847 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2849 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2851 if (rsurface.texture->shirttexture)
2852 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2854 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2856 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]);
2857 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2858 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2859 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2860 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2861 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2862 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2863 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2864 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2866 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);
2867 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2868 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]);
2869 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2870 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);}
2871 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2873 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2874 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2875 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2876 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2877 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2878 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2879 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2880 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2881 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2882 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2883 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2884 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2885 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2886 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2887 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);
2888 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2889 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2890 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2891 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2892 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2893 if (rsurfacepass == RSURFPASS_BACKGROUND)
2895 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);
2896 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);
2897 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);
2901 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);
2903 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2904 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2905 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2906 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2908 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2909 if (rsurface.rtlight)
2911 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2912 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2915 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2918 case RENDERPATH_GL11:
2919 case RENDERPATH_GL13:
2920 case RENDERPATH_GLES1:
2922 case RENDERPATH_SOFT:
2923 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);
2924 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2925 R_SetupShader_SetPermutationSoft(mode, permutation);
2926 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2927 if (mode == SHADERMODE_LIGHTSOURCE)
2929 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2930 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2931 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2932 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2933 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2934 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2936 // additive passes are only darkened by fog, not tinted
2937 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2938 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2942 if (mode == SHADERMODE_FLATCOLOR)
2944 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2946 else if (mode == SHADERMODE_LIGHTDIRECTION)
2948 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]);
2949 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2950 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);
2951 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2952 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2953 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]);
2954 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2958 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2959 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2960 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);
2961 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2962 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2964 // additive passes are only darkened by fog, not tinted
2965 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2966 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2968 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2969 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);
2970 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]);
2971 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]);
2972 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]);
2973 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]);
2974 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2975 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2976 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2977 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2979 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2980 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2981 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2982 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2983 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]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2986 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));
2987 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2988 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2990 if (rsurface.texture->pantstexture)
2991 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2993 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2995 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2997 if (rsurface.texture->shirttexture)
2998 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3000 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3002 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3003 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3004 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3005 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3006 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3007 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3008 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3009 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3010 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3012 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3013 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3014 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3015 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3017 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3018 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3019 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3020 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3021 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3022 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3023 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3024 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3025 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3026 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3027 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3028 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3029 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3030 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3031 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3032 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3033 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3034 if (rsurfacepass == RSURFPASS_BACKGROUND)
3036 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3037 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3038 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3042 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3044 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3045 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3046 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3047 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3049 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3050 if (rsurface.rtlight)
3052 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3053 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3060 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3062 // select a permutation of the lighting shader appropriate to this
3063 // combination of texture, entity, light source, and fogging, only use the
3064 // minimum features necessary to avoid wasting rendering time in the
3065 // fragment shader on features that are not being used
3066 unsigned int permutation = 0;
3067 unsigned int mode = 0;
3068 const float *lightcolorbase = rtlight->currentcolor;
3069 float ambientscale = rtlight->ambientscale;
3070 float diffusescale = rtlight->diffusescale;
3071 float specularscale = rtlight->specularscale;
3072 // this is the location of the light in view space
3073 vec3_t viewlightorigin;
3074 // this transforms from view space (camera) to light space (cubemap)
3075 matrix4x4_t viewtolight;
3076 matrix4x4_t lighttoview;
3077 float viewtolight16f[16];
3079 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3080 if (rtlight->currentcubemap != r_texture_whitecube)
3081 permutation |= SHADERPERMUTATION_CUBEFILTER;
3082 if (diffusescale > 0)
3083 permutation |= SHADERPERMUTATION_DIFFUSE;
3084 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3085 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3086 if (r_shadow_usingshadowmap2d)
3088 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3089 if (r_shadow_shadowmapvsdct)
3090 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3092 if (r_shadow_shadowmap2ddepthbuffer)
3093 permutation |= SHADERPERMUTATION_DEPTHRGB;
3095 if (vid.allowalphatocoverage)
3096 GL_AlphaToCoverage(false);
3097 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3098 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3099 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3100 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3101 switch(vid.renderpath)
3103 case RENDERPATH_D3D9:
3105 R_SetupShader_SetPermutationHLSL(mode, permutation);
3106 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3107 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3108 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3109 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3110 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3111 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3112 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3113 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);
3114 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3115 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3117 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3118 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3119 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3120 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3121 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3124 case RENDERPATH_D3D10:
3125 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3127 case RENDERPATH_D3D11:
3128 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3130 case RENDERPATH_GL20:
3131 case RENDERPATH_GLES2:
3132 R_SetupShader_SetPermutationGLSL(mode, permutation);
3133 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3134 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3135 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3136 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3137 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3138 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]);
3139 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]);
3140 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);
3141 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]);
3142 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3144 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3145 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3146 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3147 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3148 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3150 case RENDERPATH_GL11:
3151 case RENDERPATH_GL13:
3152 case RENDERPATH_GLES1:
3154 case RENDERPATH_SOFT:
3155 R_SetupShader_SetPermutationGLSL(mode, permutation);
3156 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3157 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3158 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3159 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3160 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3161 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3162 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]);
3163 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);
3164 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3165 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3167 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3168 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3169 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3170 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3171 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3176 #define SKINFRAME_HASH 1024
3180 unsigned int loadsequence; // incremented each level change
3181 memexpandablearray_t array;
3182 skinframe_t *hash[SKINFRAME_HASH];
3185 r_skinframe_t r_skinframe;
3187 void R_SkinFrame_PrepareForPurge(void)
3189 r_skinframe.loadsequence++;
3190 // wrap it without hitting zero
3191 if (r_skinframe.loadsequence >= 200)
3192 r_skinframe.loadsequence = 1;
3195 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3199 // mark the skinframe as used for the purging code
3200 skinframe->loadsequence = r_skinframe.loadsequence;
3203 void R_SkinFrame_Purge(void)
3207 for (i = 0;i < SKINFRAME_HASH;i++)
3209 for (s = r_skinframe.hash[i];s;s = s->next)
3211 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3213 if (s->merged == s->base)
3215 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3216 R_PurgeTexture(s->stain );s->stain = NULL;
3217 R_PurgeTexture(s->merged);s->merged = NULL;
3218 R_PurgeTexture(s->base );s->base = NULL;
3219 R_PurgeTexture(s->pants );s->pants = NULL;
3220 R_PurgeTexture(s->shirt );s->shirt = NULL;
3221 R_PurgeTexture(s->nmap );s->nmap = NULL;
3222 R_PurgeTexture(s->gloss );s->gloss = NULL;
3223 R_PurgeTexture(s->glow );s->glow = NULL;
3224 R_PurgeTexture(s->fog );s->fog = NULL;
3225 R_PurgeTexture(s->reflect);s->reflect = NULL;
3226 s->loadsequence = 0;
3232 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3234 char basename[MAX_QPATH];
3236 Image_StripImageExtension(name, basename, sizeof(basename));
3238 if( last == NULL ) {
3240 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3241 item = r_skinframe.hash[hashindex];
3246 // linearly search through the hash bucket
3247 for( ; item ; item = item->next ) {
3248 if( !strcmp( item->basename, basename ) ) {
3255 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3259 char basename[MAX_QPATH];
3261 Image_StripImageExtension(name, basename, sizeof(basename));
3263 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3264 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3265 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3269 rtexture_t *dyntexture;
3270 // check whether its a dynamic texture
3271 dyntexture = CL_GetDynTexture( basename );
3272 if (!add && !dyntexture)
3274 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3275 memset(item, 0, sizeof(*item));
3276 strlcpy(item->basename, basename, sizeof(item->basename));
3277 item->base = dyntexture; // either NULL or dyntexture handle
3278 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3279 item->comparewidth = comparewidth;
3280 item->compareheight = compareheight;
3281 item->comparecrc = comparecrc;
3282 item->next = r_skinframe.hash[hashindex];
3283 r_skinframe.hash[hashindex] = item;
3285 else if (textureflags & TEXF_FORCE_RELOAD)
3287 rtexture_t *dyntexture;
3288 // check whether its a dynamic texture
3289 dyntexture = CL_GetDynTexture( basename );
3290 if (!add && !dyntexture)
3292 if (item->merged == item->base)
3293 item->merged = NULL;
3294 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3295 R_PurgeTexture(item->stain );item->stain = NULL;
3296 R_PurgeTexture(item->merged);item->merged = NULL;
3297 R_PurgeTexture(item->base );item->base = NULL;
3298 R_PurgeTexture(item->pants );item->pants = NULL;
3299 R_PurgeTexture(item->shirt );item->shirt = NULL;
3300 R_PurgeTexture(item->nmap );item->nmap = NULL;
3301 R_PurgeTexture(item->gloss );item->gloss = NULL;
3302 R_PurgeTexture(item->glow );item->glow = NULL;
3303 R_PurgeTexture(item->fog );item->fog = NULL;
3304 R_PurgeTexture(item->reflect);item->reflect = NULL;
3305 item->loadsequence = 0;
3307 else if( item->base == NULL )
3309 rtexture_t *dyntexture;
3310 // check whether its a dynamic texture
3311 // 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]
3312 dyntexture = CL_GetDynTexture( basename );
3313 item->base = dyntexture; // either NULL or dyntexture handle
3316 R_SkinFrame_MarkUsed(item);
3320 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3322 unsigned long long avgcolor[5], wsum; \
3330 for(pix = 0; pix < cnt; ++pix) \
3333 for(comp = 0; comp < 3; ++comp) \
3335 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3338 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3340 for(comp = 0; comp < 3; ++comp) \
3341 avgcolor[comp] += getpixel * w; \
3344 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3345 avgcolor[4] += getpixel; \
3347 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3349 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3350 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3351 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3352 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3355 extern cvar_t gl_picmip;
3356 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3359 unsigned char *pixels;
3360 unsigned char *bumppixels;
3361 unsigned char *basepixels = NULL;
3362 int basepixels_width = 0;
3363 int basepixels_height = 0;
3364 skinframe_t *skinframe;
3365 rtexture_t *ddsbase = NULL;
3366 qboolean ddshasalpha = false;
3367 float ddsavgcolor[4];
3368 char basename[MAX_QPATH];
3369 int miplevel = R_PicmipForFlags(textureflags);
3370 int savemiplevel = miplevel;
3374 if (cls.state == ca_dedicated)
3377 // return an existing skinframe if already loaded
3378 // if loading of the first image fails, don't make a new skinframe as it
3379 // would cause all future lookups of this to be missing
3380 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3381 if (skinframe && skinframe->base)
3384 Image_StripImageExtension(name, basename, sizeof(basename));
3386 // check for DDS texture file first
3387 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3389 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3390 if (basepixels == NULL)
3394 // FIXME handle miplevel
3396 if (developer_loading.integer)
3397 Con_Printf("loading skin \"%s\"\n", name);
3399 // we've got some pixels to store, so really allocate this new texture now
3401 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3402 textureflags &= ~TEXF_FORCE_RELOAD;
3403 skinframe->stain = NULL;
3404 skinframe->merged = NULL;
3405 skinframe->base = NULL;
3406 skinframe->pants = NULL;
3407 skinframe->shirt = NULL;
3408 skinframe->nmap = NULL;
3409 skinframe->gloss = NULL;
3410 skinframe->glow = NULL;
3411 skinframe->fog = NULL;
3412 skinframe->reflect = NULL;
3413 skinframe->hasalpha = false;
3414 // we could store the q2animname here too
3418 skinframe->base = ddsbase;
3419 skinframe->hasalpha = ddshasalpha;
3420 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3421 if (r_loadfog && skinframe->hasalpha)
3422 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);
3423 //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]);
3427 basepixels_width = image_width;
3428 basepixels_height = image_height;
3429 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);
3430 if (textureflags & TEXF_ALPHA)
3432 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3434 if (basepixels[j] < 255)
3436 skinframe->hasalpha = true;
3440 if (r_loadfog && skinframe->hasalpha)
3442 // has transparent pixels
3443 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3444 for (j = 0;j < image_width * image_height * 4;j += 4)
3449 pixels[j+3] = basepixels[j+3];
3451 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);
3455 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3457 //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]);
3458 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3459 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3460 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3461 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3467 mymiplevel = savemiplevel;
3468 if (r_loadnormalmap)
3469 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);
3470 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3472 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3473 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3474 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3475 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478 // _norm is the name used by tenebrae and has been adopted as standard
3479 if (r_loadnormalmap && skinframe->nmap == NULL)
3481 mymiplevel = savemiplevel;
3482 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3484 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);
3488 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3490 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3491 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3492 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);
3494 Mem_Free(bumppixels);
3496 else if (r_shadow_bumpscale_basetexture.value > 0)
3498 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3499 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3500 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);
3504 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3505 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3509 // _luma is supported only for tenebrae compatibility
3510 // _glow is the preferred name
3511 mymiplevel = savemiplevel;
3512 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))))
3514 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);
3516 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3517 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3519 Mem_Free(pixels);pixels = NULL;
3522 mymiplevel = savemiplevel;
3523 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3525 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);
3527 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3528 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3534 mymiplevel = savemiplevel;
3535 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3537 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);
3539 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3540 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3546 mymiplevel = savemiplevel;
3547 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3549 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);
3551 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3552 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3558 mymiplevel = savemiplevel;
3559 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3561 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);
3563 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3564 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3571 Mem_Free(basepixels);
3576 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3577 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3580 unsigned char *temp1, *temp2;
3581 skinframe_t *skinframe;
3584 if (cls.state == ca_dedicated)
3587 // if already loaded just return it, otherwise make a new skinframe
3588 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3589 if (skinframe->base)
3591 textureflags &= ~TEXF_FORCE_RELOAD;
3593 skinframe->stain = NULL;
3594 skinframe->merged = NULL;
3595 skinframe->base = NULL;
3596 skinframe->pants = NULL;
3597 skinframe->shirt = NULL;
3598 skinframe->nmap = NULL;
3599 skinframe->gloss = NULL;
3600 skinframe->glow = NULL;
3601 skinframe->fog = NULL;
3602 skinframe->reflect = NULL;
3603 skinframe->hasalpha = false;
3605 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3609 if (developer_loading.integer)
3610 Con_Printf("loading 32bit skin \"%s\"\n", name);
3612 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3614 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3615 temp2 = temp1 + width * height * 4;
3616 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3617 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);
3620 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3621 if (textureflags & TEXF_ALPHA)
3623 for (i = 3;i < width * height * 4;i += 4)
3625 if (skindata[i] < 255)
3627 skinframe->hasalpha = true;
3631 if (r_loadfog && skinframe->hasalpha)
3633 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3634 memcpy(fogpixels, skindata, width * height * 4);
3635 for (i = 0;i < width * height * 4;i += 4)
3636 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3637 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3638 Mem_Free(fogpixels);
3642 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3643 //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]);
3648 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3652 skinframe_t *skinframe;
3654 if (cls.state == ca_dedicated)
3657 // if already loaded just return it, otherwise make a new skinframe
3658 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3659 if (skinframe->base)
3661 //textureflags &= ~TEXF_FORCE_RELOAD;
3663 skinframe->stain = NULL;
3664 skinframe->merged = NULL;
3665 skinframe->base = NULL;
3666 skinframe->pants = NULL;
3667 skinframe->shirt = NULL;
3668 skinframe->nmap = NULL;
3669 skinframe->gloss = NULL;
3670 skinframe->glow = NULL;
3671 skinframe->fog = NULL;
3672 skinframe->reflect = NULL;
3673 skinframe->hasalpha = false;
3675 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3679 if (developer_loading.integer)
3680 Con_Printf("loading quake skin \"%s\"\n", name);
3682 // 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)
3683 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3684 memcpy(skinframe->qpixels, skindata, width*height);
3685 skinframe->qwidth = width;
3686 skinframe->qheight = height;
3689 for (i = 0;i < width * height;i++)
3690 featuresmask |= palette_featureflags[skindata[i]];
3692 skinframe->hasalpha = false;
3693 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3694 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3695 skinframe->qgeneratemerged = true;
3696 skinframe->qgeneratebase = skinframe->qhascolormapping;
3697 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3699 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3700 //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]);
3705 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3709 unsigned char *skindata;
3712 if (!skinframe->qpixels)
3715 if (!skinframe->qhascolormapping)
3716 colormapped = false;
3720 if (!skinframe->qgeneratebase)
3725 if (!skinframe->qgeneratemerged)
3729 width = skinframe->qwidth;
3730 height = skinframe->qheight;
3731 skindata = skinframe->qpixels;
3733 if (skinframe->qgeneratenmap)
3735 unsigned char *temp1, *temp2;
3736 skinframe->qgeneratenmap = false;
3737 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3738 temp2 = temp1 + width * height * 4;
3739 // use either a custom palette or the quake palette
3740 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3741 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3742 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);
3746 if (skinframe->qgenerateglow)
3748 skinframe->qgenerateglow = false;
3749 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
3754 skinframe->qgeneratebase = false;
3755 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);
3756 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);
3757 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);
3761 skinframe->qgeneratemerged = false;
3762 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);
3765 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3767 Mem_Free(skinframe->qpixels);
3768 skinframe->qpixels = NULL;
3772 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)
3775 skinframe_t *skinframe;
3778 if (cls.state == ca_dedicated)
3781 // if already loaded just return it, otherwise make a new skinframe
3782 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3783 if (skinframe->base)
3785 textureflags &= ~TEXF_FORCE_RELOAD;
3787 skinframe->stain = NULL;
3788 skinframe->merged = NULL;
3789 skinframe->base = NULL;
3790 skinframe->pants = NULL;
3791 skinframe->shirt = NULL;
3792 skinframe->nmap = NULL;
3793 skinframe->gloss = NULL;
3794 skinframe->glow = NULL;
3795 skinframe->fog = NULL;
3796 skinframe->reflect = NULL;
3797 skinframe->hasalpha = false;
3799 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3803 if (developer_loading.integer)
3804 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3806 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3807 if (textureflags & TEXF_ALPHA)
3809 for (i = 0;i < width * height;i++)
3811 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3813 skinframe->hasalpha = true;
3817 if (r_loadfog && skinframe->hasalpha)
3818 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3821 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3822 //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]);
3827 skinframe_t *R_SkinFrame_LoadMissing(void)
3829 skinframe_t *skinframe;
3831 if (cls.state == ca_dedicated)
3834 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3835 skinframe->stain = NULL;
3836 skinframe->merged = NULL;
3837 skinframe->base = NULL;
3838 skinframe->pants = NULL;
3839 skinframe->shirt = NULL;
3840 skinframe->nmap = NULL;
3841 skinframe->gloss = NULL;
3842 skinframe->glow = NULL;
3843 skinframe->fog = NULL;
3844 skinframe->reflect = NULL;
3845 skinframe->hasalpha = false;
3847 skinframe->avgcolor[0] = rand() / RAND_MAX;
3848 skinframe->avgcolor[1] = rand() / RAND_MAX;
3849 skinframe->avgcolor[2] = rand() / RAND_MAX;
3850 skinframe->avgcolor[3] = 1;
3855 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3856 typedef struct suffixinfo_s
3859 qboolean flipx, flipy, flipdiagonal;
3862 static suffixinfo_t suffix[3][6] =
3865 {"px", false, false, false},
3866 {"nx", false, false, false},
3867 {"py", false, false, false},
3868 {"ny", false, false, false},
3869 {"pz", false, false, false},
3870 {"nz", false, false, false}
3873 {"posx", false, false, false},
3874 {"negx", false, false, false},
3875 {"posy", false, false, false},
3876 {"negy", false, false, false},
3877 {"posz", false, false, false},
3878 {"negz", false, false, false}
3881 {"rt", true, false, true},
3882 {"lf", false, true, true},
3883 {"ft", true, true, false},
3884 {"bk", false, false, false},
3885 {"up", true, false, true},
3886 {"dn", true, false, true}
3890 static int componentorder[4] = {0, 1, 2, 3};
3892 static rtexture_t *R_LoadCubemap(const char *basename)
3894 int i, j, cubemapsize;
3895 unsigned char *cubemappixels, *image_buffer;
3896 rtexture_t *cubemaptexture;
3898 // must start 0 so the first loadimagepixels has no requested width/height
3900 cubemappixels = NULL;
3901 cubemaptexture = NULL;
3902 // keep trying different suffix groups (posx, px, rt) until one loads
3903 for (j = 0;j < 3 && !cubemappixels;j++)
3905 // load the 6 images in the suffix group
3906 for (i = 0;i < 6;i++)
3908 // generate an image name based on the base and and suffix
3909 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3911 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3913 // an image loaded, make sure width and height are equal
3914 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3916 // if this is the first image to load successfully, allocate the cubemap memory
3917 if (!cubemappixels && image_width >= 1)
3919 cubemapsize = image_width;
3920 // note this clears to black, so unavailable sides are black
3921 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3923 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3925 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);
3928 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3930 Mem_Free(image_buffer);
3934 // if a cubemap loaded, upload it
3937 if (developer_loading.integer)
3938 Con_Printf("loading cubemap \"%s\"\n", basename);
3940 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);
3941 Mem_Free(cubemappixels);
3945 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3946 if (developer_loading.integer)
3948 Con_Printf("(tried tried images ");
3949 for (j = 0;j < 3;j++)
3950 for (i = 0;i < 6;i++)
3951 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3952 Con_Print(" and was unable to find any of them).\n");
3955 return cubemaptexture;
3958 rtexture_t *R_GetCubemap(const char *basename)
3961 for (i = 0;i < r_texture_numcubemaps;i++)
3962 if (r_texture_cubemaps[i] != NULL)
3963 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3964 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3965 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3966 return r_texture_whitecube;
3967 r_texture_numcubemaps++;
3968 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3969 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3970 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3971 return r_texture_cubemaps[i]->texture;
3974 static void R_Main_FreeViewCache(void)
3976 if (r_refdef.viewcache.entityvisible)
3977 Mem_Free(r_refdef.viewcache.entityvisible);
3978 if (r_refdef.viewcache.world_pvsbits)
3979 Mem_Free(r_refdef.viewcache.world_pvsbits);
3980 if (r_refdef.viewcache.world_leafvisible)
3981 Mem_Free(r_refdef.viewcache.world_leafvisible);
3982 if (r_refdef.viewcache.world_surfacevisible)
3983 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3984 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3987 static void R_Main_ResizeViewCache(void)
3989 int numentities = r_refdef.scene.numentities;
3990 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3991 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3992 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3993 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3994 if (r_refdef.viewcache.maxentities < numentities)
3996 r_refdef.viewcache.maxentities = numentities;
3997 if (r_refdef.viewcache.entityvisible)
3998 Mem_Free(r_refdef.viewcache.entityvisible);
3999 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4001 if (r_refdef.viewcache.world_numclusters != numclusters)
4003 r_refdef.viewcache.world_numclusters = numclusters;
4004 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4005 if (r_refdef.viewcache.world_pvsbits)
4006 Mem_Free(r_refdef.viewcache.world_pvsbits);
4007 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4009 if (r_refdef.viewcache.world_numleafs != numleafs)
4011 r_refdef.viewcache.world_numleafs = numleafs;
4012 if (r_refdef.viewcache.world_leafvisible)
4013 Mem_Free(r_refdef.viewcache.world_leafvisible);
4014 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4016 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4018 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4019 if (r_refdef.viewcache.world_surfacevisible)
4020 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4021 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4025 extern rtexture_t *loadingscreentexture;
4026 static void gl_main_start(void)
4028 loadingscreentexture = NULL;
4029 r_texture_blanknormalmap = NULL;
4030 r_texture_white = NULL;
4031 r_texture_grey128 = NULL;
4032 r_texture_black = NULL;
4033 r_texture_whitecube = NULL;
4034 r_texture_normalizationcube = NULL;
4035 r_texture_fogattenuation = NULL;
4036 r_texture_fogheighttexture = NULL;
4037 r_texture_gammaramps = NULL;
4038 r_texture_numcubemaps = 0;
4039 r_uniformbufferalignment = 32;
4041 r_loaddds = r_texture_dds_load.integer != 0;
4042 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4044 switch(vid.renderpath)
4046 case RENDERPATH_GL20:
4047 case RENDERPATH_D3D9:
4048 case RENDERPATH_D3D10:
4049 case RENDERPATH_D3D11:
4050 case RENDERPATH_SOFT:
4051 case RENDERPATH_GLES2:
4052 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4053 Cvar_SetValueQuick(&gl_combine, 1);
4054 Cvar_SetValueQuick(&r_glsl, 1);
4055 r_loadnormalmap = true;
4058 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4059 if (vid.support.arb_uniform_buffer_object)
4060 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4063 case RENDERPATH_GL13:
4064 case RENDERPATH_GLES1:
4065 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4066 Cvar_SetValueQuick(&gl_combine, 1);
4067 Cvar_SetValueQuick(&r_glsl, 0);
4068 r_loadnormalmap = false;
4069 r_loadgloss = false;
4072 case RENDERPATH_GL11:
4073 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4074 Cvar_SetValueQuick(&gl_combine, 0);
4075 Cvar_SetValueQuick(&r_glsl, 0);
4076 r_loadnormalmap = false;
4077 r_loadgloss = false;
4083 R_FrameData_Reset();
4084 R_BufferData_Reset();
4088 memset(r_queries, 0, sizeof(r_queries));
4090 r_qwskincache = NULL;
4091 r_qwskincache_size = 0;
4093 // due to caching of texture_t references, the collision cache must be reset
4094 Collision_Cache_Reset(true);
4096 // set up r_skinframe loading system for textures
4097 memset(&r_skinframe, 0, sizeof(r_skinframe));
4098 r_skinframe.loadsequence = 1;
4099 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4101 r_main_texturepool = R_AllocTexturePool();
4102 R_BuildBlankTextures();
4104 if (vid.support.arb_texture_cube_map)
4107 R_BuildNormalizationCube();
4109 r_texture_fogattenuation = NULL;
4110 r_texture_fogheighttexture = NULL;
4111 r_texture_gammaramps = NULL;
4112 //r_texture_fogintensity = NULL;
4113 memset(&r_fb, 0, sizeof(r_fb));
4114 r_glsl_permutation = NULL;
4115 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4116 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4117 glslshaderstring = NULL;
4119 r_hlsl_permutation = NULL;
4120 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4121 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4123 hlslshaderstring = NULL;
4124 memset(&r_svbsp, 0, sizeof (r_svbsp));
4126 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4127 r_texture_numcubemaps = 0;
4129 r_refdef.fogmasktable_density = 0;
4132 // For Steelstorm Android
4133 // FIXME CACHE the program and reload
4134 // FIXME see possible combinations for SS:BR android
4135 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4136 R_SetupShader_SetPermutationGLSL(0, 12);
4137 R_SetupShader_SetPermutationGLSL(0, 13);
4138 R_SetupShader_SetPermutationGLSL(0, 8388621);
4139 R_SetupShader_SetPermutationGLSL(3, 0);
4140 R_SetupShader_SetPermutationGLSL(3, 2048);
4141 R_SetupShader_SetPermutationGLSL(5, 0);
4142 R_SetupShader_SetPermutationGLSL(5, 2);
4143 R_SetupShader_SetPermutationGLSL(5, 2048);
4144 R_SetupShader_SetPermutationGLSL(5, 8388608);
4145 R_SetupShader_SetPermutationGLSL(11, 1);
4146 R_SetupShader_SetPermutationGLSL(11, 2049);
4147 R_SetupShader_SetPermutationGLSL(11, 8193);
4148 R_SetupShader_SetPermutationGLSL(11, 10241);
4149 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4153 static void gl_main_shutdown(void)
4156 R_FrameData_Reset();
4157 R_BufferData_Reset();
4159 R_Main_FreeViewCache();
4161 switch(vid.renderpath)
4163 case RENDERPATH_GL11:
4164 case RENDERPATH_GL13:
4165 case RENDERPATH_GL20:
4166 case RENDERPATH_GLES1:
4167 case RENDERPATH_GLES2:
4168 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4170 qglDeleteQueriesARB(r_maxqueries, r_queries);
4173 case RENDERPATH_D3D9:
4174 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4176 case RENDERPATH_D3D10:
4177 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4179 case RENDERPATH_D3D11:
4180 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4182 case RENDERPATH_SOFT:
4188 memset(r_queries, 0, sizeof(r_queries));
4190 r_qwskincache = NULL;
4191 r_qwskincache_size = 0;
4193 // clear out the r_skinframe state
4194 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4195 memset(&r_skinframe, 0, sizeof(r_skinframe));
4198 Mem_Free(r_svbsp.nodes);
4199 memset(&r_svbsp, 0, sizeof (r_svbsp));
4200 R_FreeTexturePool(&r_main_texturepool);
4201 loadingscreentexture = NULL;
4202 r_texture_blanknormalmap = NULL;
4203 r_texture_white = NULL;
4204 r_texture_grey128 = NULL;
4205 r_texture_black = NULL;
4206 r_texture_whitecube = NULL;
4207 r_texture_normalizationcube = NULL;
4208 r_texture_fogattenuation = NULL;
4209 r_texture_fogheighttexture = NULL;
4210 r_texture_gammaramps = NULL;
4211 r_texture_numcubemaps = 0;
4212 //r_texture_fogintensity = NULL;
4213 memset(&r_fb, 0, sizeof(r_fb));
4216 r_glsl_permutation = NULL;
4217 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4218 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4219 glslshaderstring = NULL;
4221 r_hlsl_permutation = NULL;
4222 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4223 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4225 hlslshaderstring = NULL;
4228 static void gl_main_newmap(void)
4230 // FIXME: move this code to client
4231 char *entities, entname[MAX_QPATH];
4233 Mem_Free(r_qwskincache);
4234 r_qwskincache = NULL;
4235 r_qwskincache_size = 0;
4238 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4239 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4241 CL_ParseEntityLump(entities);
4245 if (cl.worldmodel->brush.entities)
4246 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4248 R_Main_FreeViewCache();
4250 R_FrameData_Reset();
4251 R_BufferData_Reset();
4254 void GL_Main_Init(void)
4257 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4259 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4260 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4261 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4262 if (gamemode == GAME_NEHAHRA)
4264 Cvar_RegisterVariable (&gl_fogenable);
4265 Cvar_RegisterVariable (&gl_fogdensity);
4266 Cvar_RegisterVariable (&gl_fogred);
4267 Cvar_RegisterVariable (&gl_foggreen);
4268 Cvar_RegisterVariable (&gl_fogblue);
4269 Cvar_RegisterVariable (&gl_fogstart);
4270 Cvar_RegisterVariable (&gl_fogend);
4271 Cvar_RegisterVariable (&gl_skyclip);
4273 Cvar_RegisterVariable(&r_motionblur);
4274 Cvar_RegisterVariable(&r_damageblur);
4275 Cvar_RegisterVariable(&r_motionblur_averaging);
4276 Cvar_RegisterVariable(&r_motionblur_randomize);
4277 Cvar_RegisterVariable(&r_motionblur_minblur);
4278 Cvar_RegisterVariable(&r_motionblur_maxblur);
4279 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4280 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4281 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4282 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4283 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4284 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4285 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4286 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4287 Cvar_RegisterVariable(&r_equalize_entities_by);
4288 Cvar_RegisterVariable(&r_equalize_entities_to);
4289 Cvar_RegisterVariable(&r_depthfirst);
4290 Cvar_RegisterVariable(&r_useinfinitefarclip);
4291 Cvar_RegisterVariable(&r_farclip_base);
4292 Cvar_RegisterVariable(&r_farclip_world);
4293 Cvar_RegisterVariable(&r_nearclip);
4294 Cvar_RegisterVariable(&r_deformvertexes);
4295 Cvar_RegisterVariable(&r_transparent);
4296 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4297 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4298 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4299 Cvar_RegisterVariable(&r_showoverdraw);
4300 Cvar_RegisterVariable(&r_showbboxes);
4301 Cvar_RegisterVariable(&r_showsurfaces);
4302 Cvar_RegisterVariable(&r_showtris);
4303 Cvar_RegisterVariable(&r_shownormals);
4304 Cvar_RegisterVariable(&r_showlighting);
4305 Cvar_RegisterVariable(&r_showshadowvolumes);
4306 Cvar_RegisterVariable(&r_showcollisionbrushes);
4307 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4308 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4309 Cvar_RegisterVariable(&r_showdisabledepthtest);
4310 Cvar_RegisterVariable(&r_drawportals);
4311 Cvar_RegisterVariable(&r_drawentities);
4312 Cvar_RegisterVariable(&r_draw2d);
4313 Cvar_RegisterVariable(&r_drawworld);
4314 Cvar_RegisterVariable(&r_cullentities_trace);
4315 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4316 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4317 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4318 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4319 Cvar_RegisterVariable(&r_sortentities);
4320 Cvar_RegisterVariable(&r_drawviewmodel);
4321 Cvar_RegisterVariable(&r_drawexteriormodel);
4322 Cvar_RegisterVariable(&r_speeds);
4323 Cvar_RegisterVariable(&r_fullbrights);
4324 Cvar_RegisterVariable(&r_wateralpha);
4325 Cvar_RegisterVariable(&r_dynamic);
4326 Cvar_RegisterVariable(&r_fakelight);
4327 Cvar_RegisterVariable(&r_fakelight_intensity);
4328 Cvar_RegisterVariable(&r_fullbright);
4329 Cvar_RegisterVariable(&r_shadows);
4330 Cvar_RegisterVariable(&r_shadows_darken);
4331 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4332 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4333 Cvar_RegisterVariable(&r_shadows_throwdistance);
4334 Cvar_RegisterVariable(&r_shadows_throwdirection);
4335 Cvar_RegisterVariable(&r_shadows_focus);
4336 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4337 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4338 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4339 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4340 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4341 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4342 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4343 Cvar_RegisterVariable(&r_fog_exp2);
4344 Cvar_RegisterVariable(&r_fog_clear);
4345 Cvar_RegisterVariable(&r_drawfog);
4346 Cvar_RegisterVariable(&r_transparentdepthmasking);
4347 Cvar_RegisterVariable(&r_transparent_sortmindist);
4348 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4349 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4350 Cvar_RegisterVariable(&r_texture_dds_load);
4351 Cvar_RegisterVariable(&r_texture_dds_save);
4352 Cvar_RegisterVariable(&r_textureunits);
4353 Cvar_RegisterVariable(&gl_combine);
4354 Cvar_RegisterVariable(&r_usedepthtextures);
4355 Cvar_RegisterVariable(&r_viewfbo);
4356 Cvar_RegisterVariable(&r_viewscale);
4357 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4358 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4359 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4360 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4361 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4362 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4363 Cvar_RegisterVariable(&r_glsl);
4364 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4365 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4366 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4367 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4368 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4369 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4370 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4371 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4372 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4373 Cvar_RegisterVariable(&r_glsl_postprocess);
4374 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4375 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4376 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4377 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4378 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4379 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4380 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4381 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4382 Cvar_RegisterVariable(&r_celshading);
4383 Cvar_RegisterVariable(&r_celoutlines);
4385 Cvar_RegisterVariable(&r_water);
4386 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4387 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4388 Cvar_RegisterVariable(&r_water_clippingplanebias);
4389 Cvar_RegisterVariable(&r_water_refractdistort);
4390 Cvar_RegisterVariable(&r_water_reflectdistort);
4391 Cvar_RegisterVariable(&r_water_scissormode);
4392 Cvar_RegisterVariable(&r_water_lowquality);
4393 Cvar_RegisterVariable(&r_water_hideplayer);
4394 Cvar_RegisterVariable(&r_water_fbo);
4396 Cvar_RegisterVariable(&r_lerpsprites);
4397 Cvar_RegisterVariable(&r_lerpmodels);
4398 Cvar_RegisterVariable(&r_lerplightstyles);
4399 Cvar_RegisterVariable(&r_waterscroll);
4400 Cvar_RegisterVariable(&r_bloom);
4401 Cvar_RegisterVariable(&r_bloom_colorscale);
4402 Cvar_RegisterVariable(&r_bloom_brighten);
4403 Cvar_RegisterVariable(&r_bloom_blur);
4404 Cvar_RegisterVariable(&r_bloom_resolution);
4405 Cvar_RegisterVariable(&r_bloom_colorexponent);
4406 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4407 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4408 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4409 Cvar_RegisterVariable(&r_hdr_glowintensity);
4410 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4411 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4412 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4413 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4414 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4415 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4416 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4417 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4418 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4419 Cvar_RegisterVariable(&developer_texturelogging);
4420 Cvar_RegisterVariable(&gl_lightmaps);
4421 Cvar_RegisterVariable(&r_test);
4422 Cvar_RegisterVariable(&r_batch_multidraw);
4423 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4424 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4425 Cvar_RegisterVariable(&r_glsl_skeletal);
4426 Cvar_RegisterVariable(&r_glsl_saturation);
4427 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4428 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4429 Cvar_RegisterVariable(&r_framedatasize);
4430 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4431 Cvar_RegisterVariable(&r_buffermegs[i]);
4432 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4433 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4434 Cvar_SetValue("r_fullbrights", 0);
4435 #ifdef DP_MOBILETOUCH
4436 // GLES devices have terrible depth precision in general, so...
4437 Cvar_SetValueQuick(&r_nearclip, 4);
4438 Cvar_SetValueQuick(&r_farclip_base, 4096);
4439 Cvar_SetValueQuick(&r_farclip_world, 0);
4440 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4442 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4445 void Render_Init(void)
4458 R_LightningBeams_Init();
4468 extern char *ENGINE_EXTENSIONS;
4471 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4472 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4473 gl_version = (const char *)qglGetString(GL_VERSION);
4474 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4478 if (!gl_platformextensions)
4479 gl_platformextensions = "";
4481 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4482 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4483 Con_Printf("GL_VERSION: %s\n", gl_version);
4484 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4485 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4487 VID_CheckExtensions();
4489 // LordHavoc: report supported extensions
4491 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4493 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4496 // clear to black (loading plaque will be seen over this)
4497 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4501 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4505 if (r_trippy.integer)
4507 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4509 p = r_refdef.view.frustum + i;
4514 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4518 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4522 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4526 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4530 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4534 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4538 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4542 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4550 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4554 if (r_trippy.integer)
4556 for (i = 0;i < numplanes;i++)
4563 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4567 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4571 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4575 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4579 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4583 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4587 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4591 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4599 //==================================================================================
4601 // LordHavoc: this stores temporary data used within the same frame
4603 typedef struct r_framedata_mem_s
4605 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4606 size_t size; // how much usable space
4607 size_t current; // how much space in use
4608 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4609 size_t wantedsize; // how much space was allocated
4610 unsigned char *data; // start of real data (16byte aligned)
4614 static r_framedata_mem_t *r_framedata_mem;
4616 void R_FrameData_Reset(void)
4618 while (r_framedata_mem)
4620 r_framedata_mem_t *next = r_framedata_mem->purge;
4621 Mem_Free(r_framedata_mem);
4622 r_framedata_mem = next;
4626 static void R_FrameData_Resize(qboolean mustgrow)
4629 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4630 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4631 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4633 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4634 newmem->wantedsize = wantedsize;
4635 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4636 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4637 newmem->current = 0;
4639 newmem->purge = r_framedata_mem;
4640 r_framedata_mem = newmem;
4644 void R_FrameData_NewFrame(void)
4646 R_FrameData_Resize(false);
4647 if (!r_framedata_mem)
4649 // if we ran out of space on the last frame, free the old memory now
4650 while (r_framedata_mem->purge)
4652 // repeatedly remove the second item in the list, leaving only head
4653 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4654 Mem_Free(r_framedata_mem->purge);
4655 r_framedata_mem->purge = next;
4657 // reset the current mem pointer
4658 r_framedata_mem->current = 0;
4659 r_framedata_mem->mark = 0;
4662 void *R_FrameData_Alloc(size_t size)
4667 // align to 16 byte boundary - the data pointer is already aligned, so we
4668 // only need to ensure the size of every allocation is also aligned
4669 size = (size + 15) & ~15;
4671 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4673 // emergency - we ran out of space, allocate more memory
4674 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4675 // this might not be a growing it, but we'll allocate another buffer every time
4676 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4677 R_FrameData_Resize(true);
4680 data = r_framedata_mem->data + r_framedata_mem->current;
4681 r_framedata_mem->current += size;
4683 // count the usage for stats
4684 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4685 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4687 return (void *)data;
4690 void *R_FrameData_Store(size_t size, void *data)
4692 void *d = R_FrameData_Alloc(size);
4694 memcpy(d, data, size);
4698 void R_FrameData_SetMark(void)
4700 if (!r_framedata_mem)
4702 r_framedata_mem->mark = r_framedata_mem->current;
4705 void R_FrameData_ReturnToMark(void)
4707 if (!r_framedata_mem)
4709 r_framedata_mem->current = r_framedata_mem->mark;
4712 //==================================================================================
4714 // avoid reusing the same buffer objects on consecutive frames
4715 #define R_BUFFERDATA_CYCLE 3
4717 typedef struct r_bufferdata_buffer_s
4719 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4720 size_t size; // how much usable space
4721 size_t current; // how much space in use
4722 r_meshbuffer_t *buffer; // the buffer itself
4724 r_bufferdata_buffer_t;
4726 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4727 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4729 /// frees all dynamic buffers
4730 void R_BufferData_Reset(void)
4733 r_bufferdata_buffer_t **p, *mem;
4734 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4736 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4739 p = &r_bufferdata_buffer[cycle][type];
4745 R_Mesh_DestroyMeshBuffer(mem->buffer);
4752 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4753 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4755 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4757 float newvalue = r_buffermegs[type].value;
4759 // increase the cvar if we have to (but only if we already have a mem)
4760 if (mustgrow && mem)
4762 newvalue = bound(0.25f, newvalue, 256.0f);
4763 while (newvalue * 1024*1024 < minsize)
4766 // clamp the cvar to valid range
4767 newvalue = bound(0.25f, newvalue, 256.0f);
4768 if (r_buffermegs[type].value != newvalue)
4769 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4771 // calculate size in bytes
4772 size = (size_t)(newvalue * 1024*1024);
4773 size = bound(131072, size, 256*1024*1024);
4775 // allocate a new buffer if the size is different (purge old one later)
4776 // or if we were told we must grow the buffer
4777 if (!mem || mem->size != size || mustgrow)
4779 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4782 if (type == R_BUFFERDATA_VERTEX)
4783 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4784 else if (type == R_BUFFERDATA_INDEX16)
4785 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4786 else if (type == R_BUFFERDATA_INDEX32)
4787 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4788 else if (type == R_BUFFERDATA_UNIFORM)
4789 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4790 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4791 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4795 void R_BufferData_NewFrame(void)
4798 r_bufferdata_buffer_t **p, *mem;
4799 // cycle to the next frame's buffers
4800 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4801 // if we ran out of space on the last time we used these buffers, free the old memory now
4802 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4804 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4806 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4807 // free all but the head buffer, this is how we recycle obsolete
4808 // buffers after they are no longer in use
4809 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4815 R_Mesh_DestroyMeshBuffer(mem->buffer);
4818 // reset the current offset
4819 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4824 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4826 r_bufferdata_buffer_t *mem;
4830 *returnbufferoffset = 0;
4832 // align size to a byte boundary appropriate for the buffer type, this
4833 // makes all allocations have aligned start offsets
4834 if (type == R_BUFFERDATA_UNIFORM)
4835 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4837 padsize = (datasize + 15) & ~15;
4839 // if we ran out of space in this buffer we must allocate a new one
4840 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4841 R_BufferData_Resize(type, true, padsize);
4843 // if the resize did not give us enough memory, fail
4844 if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4845 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4847 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4848 offset = (int)mem->current;
4849 mem->current += padsize;
4851 // upload the data to the buffer at the chosen offset
4853 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4854 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4856 // count the usage for stats
4857 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4858 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4860 // return the buffer offset
4861 *returnbufferoffset = offset;
4866 //==================================================================================
4868 // LordHavoc: animcache originally written by Echon, rewritten since then
4871 * Animation cache prevents re-generating mesh data for an animated model
4872 * multiple times in one frame for lighting, shadowing, reflections, etc.
4875 void R_AnimCache_Free(void)
4879 void R_AnimCache_ClearCache(void)
4882 entity_render_t *ent;
4884 for (i = 0;i < r_refdef.scene.numentities;i++)
4886 ent = r_refdef.scene.entities[i];
4887 ent->animcache_vertex3f = NULL;
4888 ent->animcache_vertex3f_vertexbuffer = NULL;
4889 ent->animcache_vertex3f_bufferoffset = 0;
4890 ent->animcache_normal3f = NULL;
4891 ent->animcache_normal3f_vertexbuffer = NULL;
4892 ent->animcache_normal3f_bufferoffset = 0;
4893 ent->animcache_svector3f = NULL;
4894 ent->animcache_svector3f_vertexbuffer = NULL;
4895 ent->animcache_svector3f_bufferoffset = 0;
4896 ent->animcache_tvector3f = NULL;
4897 ent->animcache_tvector3f_vertexbuffer = NULL;
4898 ent->animcache_tvector3f_bufferoffset = 0;
4899 ent->animcache_vertexmesh = NULL;
4900 ent->animcache_vertexmesh_vertexbuffer = NULL;
4901 ent->animcache_vertexmesh_bufferoffset = 0;
4902 ent->animcache_skeletaltransform3x4 = NULL;
4903 ent->animcache_skeletaltransform3x4buffer = NULL;
4904 ent->animcache_skeletaltransform3x4offset = 0;
4905 ent->animcache_skeletaltransform3x4size = 0;
4909 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4913 // check if we need the meshbuffers
4914 if (!vid.useinterleavedarrays)
4917 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4918 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4919 // TODO: upload vertexbuffer?
4920 if (ent->animcache_vertexmesh)
4922 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4923 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4924 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4925 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4926 for (i = 0;i < numvertices;i++)
4927 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4928 if (ent->animcache_svector3f)
4929 for (i = 0;i < numvertices;i++)
4930 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4931 if (ent->animcache_tvector3f)
4932 for (i = 0;i < numvertices;i++)
4933 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4934 if (ent->animcache_normal3f)
4935 for (i = 0;i < numvertices;i++)
4936 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4940 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4942 dp_model_t *model = ent->model;
4945 // see if this ent is worth caching
4946 if (!model || !model->Draw || !model->AnimateVertices)
4948 // nothing to cache if it contains no animations and has no skeleton
4949 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4951 // see if it is already cached for gpuskeletal
4952 if (ent->animcache_skeletaltransform3x4)
4954 // see if it is already cached as a mesh
4955 if (ent->animcache_vertex3f)
4957 // check if we need to add normals or tangents
4958 if (ent->animcache_normal3f)
4959 wantnormals = false;
4960 if (ent->animcache_svector3f)
4961 wanttangents = false;
4962 if (!wantnormals && !wanttangents)
4966 // check which kind of cache we need to generate
4967 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4969 // cache the skeleton so the vertex shader can use it
4970 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4971 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4972 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4973 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4974 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4975 // note: this can fail if the buffer is at the grow limit
4976 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4977 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4979 else if (ent->animcache_vertex3f)
4981 // mesh was already cached but we may need to add normals/tangents
4982 // (this only happens with multiple views, reflections, cameras, etc)
4983 if (wantnormals || wanttangents)
4985 numvertices = model->surfmesh.num_vertices;
4987 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4990 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4991 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4993 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4994 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4995 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4996 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4997 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5002 // generate mesh cache
5003 numvertices = model->surfmesh.num_vertices;
5004 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5006 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5009 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5010 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5012 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5013 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5014 if (wantnormals || wanttangents)
5016 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5017 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5018 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5020 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5021 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5022 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5027 void R_AnimCache_CacheVisibleEntities(void)
5030 qboolean wantnormals = true;
5031 qboolean wanttangents = !r_showsurfaces.integer;
5033 switch(vid.renderpath)
5035 case RENDERPATH_GL20:
5036 case RENDERPATH_D3D9:
5037 case RENDERPATH_D3D10:
5038 case RENDERPATH_D3D11:
5039 case RENDERPATH_GLES2:
5041 case RENDERPATH_GL11:
5042 case RENDERPATH_GL13:
5043 case RENDERPATH_GLES1:
5044 wanttangents = false;
5046 case RENDERPATH_SOFT:
5050 if (r_shownormals.integer)
5051 wanttangents = wantnormals = true;
5053 // TODO: thread this
5054 // NOTE: R_PrepareRTLights() also caches entities
5056 for (i = 0;i < r_refdef.scene.numentities;i++)
5057 if (r_refdef.viewcache.entityvisible[i])
5058 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5061 //==================================================================================
5063 extern cvar_t r_overheadsprites_pushback;
5065 static void R_View_UpdateEntityLighting (void)
5068 entity_render_t *ent;
5069 vec3_t tempdiffusenormal, avg;
5070 vec_t f, fa, fd, fdd;
5071 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5073 for (i = 0;i < r_refdef.scene.numentities;i++)
5075 ent = r_refdef.scene.entities[i];
5077 // skip unseen models
5078 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5082 if (ent->model && ent->model == cl.worldmodel)
5084 // TODO: use modellight for r_ambient settings on world?
5085 VectorSet(ent->modellight_ambient, 0, 0, 0);
5086 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5087 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5091 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5093 // aleady updated by CSQC
5094 // TODO: force modellight on BSP models in this case?
5095 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5099 // fetch the lighting from the worldmodel data
5100 VectorClear(ent->modellight_ambient);
5101 VectorClear(ent->modellight_diffuse);
5102 VectorClear(tempdiffusenormal);
5103 if (ent->flags & RENDER_LIGHT)
5106 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5108 // complete lightning for lit sprites
5109 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5110 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5112 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5113 org[2] = org[2] + r_overheadsprites_pushback.value;
5114 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5117 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5119 if(ent->flags & RENDER_EQUALIZE)
5121 // first fix up ambient lighting...
5122 if(r_equalize_entities_minambient.value > 0)
5124 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5127 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5128 if(fa < r_equalize_entities_minambient.value * fd)
5131 // fa'/fd' = minambient
5132 // fa'+0.25*fd' = fa+0.25*fd
5134 // fa' = fd' * minambient
5135 // fd'*(0.25+minambient) = fa+0.25*fd
5137 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5138 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5140 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5141 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
5142 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5143 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5148 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5150 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5151 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5155 // adjust brightness and saturation to target
5156 avg[0] = avg[1] = avg[2] = fa / f;
5157 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5158 avg[0] = avg[1] = avg[2] = fd / f;
5159 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5165 VectorSet(ent->modellight_ambient, 1, 1, 1);
5168 // move the light direction into modelspace coordinates for lighting code
5169 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5170 if(VectorLength2(ent->modellight_lightdir) == 0)
5171 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5172 VectorNormalize(ent->modellight_lightdir);
5176 #define MAX_LINEOFSIGHTTRACES 64
5178 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5181 vec3_t boxmins, boxmaxs;
5184 dp_model_t *model = r_refdef.scene.worldmodel;
5186 if (!model || !model->brush.TraceLineOfSight)
5189 // expand the box a little
5190 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5191 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5192 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5193 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5194 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5195 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5197 // return true if eye is inside enlarged box
5198 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5202 VectorCopy(eye, start);
5203 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5204 if (model->brush.TraceLineOfSight(model, start, end))
5207 // try various random positions
5208 for (i = 0;i < numsamples;i++)
5210 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5211 if (model->brush.TraceLineOfSight(model, start, end))
5219 static void R_View_UpdateEntityVisible (void)
5224 entity_render_t *ent;
5226 if (r_refdef.envmap || r_fb.water.hideplayer)
5227 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5228 else if (chase_active.integer || r_fb.water.renderingscene)
5229 renderimask = RENDER_VIEWMODEL;
5231 renderimask = RENDER_EXTERIORMODEL;
5232 if (!r_drawviewmodel.integer)
5233 renderimask |= RENDER_VIEWMODEL;
5234 if (!r_drawexteriormodel.integer)
5235 renderimask |= RENDER_EXTERIORMODEL;
5236 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5237 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5239 // worldmodel can check visibility
5240 for (i = 0;i < r_refdef.scene.numentities;i++)
5242 ent = r_refdef.scene.entities[i];
5243 if (!(ent->flags & renderimask))
5244 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)))
5245 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))
5246 r_refdef.viewcache.entityvisible[i] = true;
5251 // no worldmodel or it can't check visibility
5252 for (i = 0;i < r_refdef.scene.numentities;i++)
5254 ent = r_refdef.scene.entities[i];
5255 if (!(ent->flags & renderimask))
5256 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)))
5257 r_refdef.viewcache.entityvisible[i] = true;
5260 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5261 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5263 for (i = 0;i < r_refdef.scene.numentities;i++)
5265 if (!r_refdef.viewcache.entityvisible[i])
5267 ent = r_refdef.scene.entities[i];
5268 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5270 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5272 continue; // temp entities do pvs only
5273 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5274 ent->last_trace_visibility = realtime;
5275 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5276 r_refdef.viewcache.entityvisible[i] = 0;
5282 /// only used if skyrendermasked, and normally returns false
5283 static int R_DrawBrushModelsSky (void)
5286 entity_render_t *ent;
5289 for (i = 0;i < r_refdef.scene.numentities;i++)
5291 if (!r_refdef.viewcache.entityvisible[i])
5293 ent = r_refdef.scene.entities[i];
5294 if (!ent->model || !ent->model->DrawSky)
5296 ent->model->DrawSky(ent);
5302 static void R_DrawNoModel(entity_render_t *ent);
5303 static void R_DrawModels(void)
5306 entity_render_t *ent;
5308 for (i = 0;i < r_refdef.scene.numentities;i++)
5310 if (!r_refdef.viewcache.entityvisible[i])
5312 ent = r_refdef.scene.entities[i];
5313 r_refdef.stats[r_stat_entities]++;
5315 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5318 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5319 Con_Printf("R_DrawModels\n");
5320 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]);
5321 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);
5322 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);
5325 if (ent->model && ent->model->Draw != NULL)
5326 ent->model->Draw(ent);
5332 static void R_DrawModelsDepth(void)
5335 entity_render_t *ent;
5337 for (i = 0;i < r_refdef.scene.numentities;i++)
5339 if (!r_refdef.viewcache.entityvisible[i])
5341 ent = r_refdef.scene.entities[i];
5342 if (ent->model && ent->model->DrawDepth != NULL)
5343 ent->model->DrawDepth(ent);
5347 static void R_DrawModelsDebug(void)
5350 entity_render_t *ent;
5352 for (i = 0;i < r_refdef.scene.numentities;i++)
5354 if (!r_refdef.viewcache.entityvisible[i])
5356 ent = r_refdef.scene.entities[i];
5357 if (ent->model && ent->model->DrawDebug != NULL)
5358 ent->model->DrawDebug(ent);
5362 static void R_DrawModelsAddWaterPlanes(void)
5365 entity_render_t *ent;
5367 for (i = 0;i < r_refdef.scene.numentities;i++)
5369 if (!r_refdef.viewcache.entityvisible[i])
5371 ent = r_refdef.scene.entities[i];
5372 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5373 ent->model->DrawAddWaterPlanes(ent);
5377 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}};
5379 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5381 if (r_hdr_irisadaptation.integer)
5386 vec3_t diffusenormal;
5388 vec_t brightness = 0.0f;
5393 VectorCopy(r_refdef.view.forward, forward);
5394 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5396 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5397 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5398 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5399 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5400 d = DotProduct(forward, diffusenormal);
5401 brightness += VectorLength(ambient);
5403 brightness += d * VectorLength(diffuse);
5405 brightness *= 1.0f / c;
5406 brightness += 0.00001f; // make sure it's never zero
5407 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5408 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5409 current = r_hdr_irisadaptation_value.value;
5411 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5412 else if (current > goal)
5413 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5414 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5415 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5417 else if (r_hdr_irisadaptation_value.value != 1.0f)
5418 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5421 static void R_View_SetFrustum(const int *scissor)
5424 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5425 vec3_t forward, left, up, origin, v;
5429 // flipped x coordinates (because x points left here)
5430 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5431 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5433 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5434 switch(vid.renderpath)
5436 case RENDERPATH_D3D9:
5437 case RENDERPATH_D3D10:
5438 case RENDERPATH_D3D11:
5439 // non-flipped y coordinates
5440 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5441 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5443 case RENDERPATH_SOFT:
5444 case RENDERPATH_GL11:
5445 case RENDERPATH_GL13:
5446 case RENDERPATH_GL20:
5447 case RENDERPATH_GLES1:
5448 case RENDERPATH_GLES2:
5449 // non-flipped y coordinates
5450 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5451 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5456 // we can't trust r_refdef.view.forward and friends in reflected scenes
5457 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5460 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5461 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5462 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5463 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5464 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5465 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5466 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5467 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5468 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5469 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5470 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5471 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5475 zNear = r_refdef.nearclip;
5476 nudge = 1.0 - 1.0 / (1<<23);
5477 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5478 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5479 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5480 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5481 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5482 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5483 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5484 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5490 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5491 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5492 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5493 r_refdef.view.frustum[0].dist = m[15] - m[12];
5495 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5496 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5497 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5498 r_refdef.view.frustum[1].dist = m[15] + m[12];
5500 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5501 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5502 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5503 r_refdef.view.frustum[2].dist = m[15] - m[13];
5505 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5506 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5507 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5508 r_refdef.view.frustum[3].dist = m[15] + m[13];
5510 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5511 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5512 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5513 r_refdef.view.frustum[4].dist = m[15] - m[14];
5515 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5516 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5517 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5518 r_refdef.view.frustum[5].dist = m[15] + m[14];
5521 if (r_refdef.view.useperspective)
5523 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5524 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]);
5525 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]);
5526 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]);
5527 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]);
5529 // then the normals from the corners relative to origin
5530 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5531 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5532 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5533 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5535 // in a NORMAL view, forward cross left == up
5536 // in a REFLECTED view, forward cross left == down
5537 // so our cross products above need to be adjusted for a left handed coordinate system
5538 CrossProduct(forward, left, v);
5539 if(DotProduct(v, up) < 0)
5541 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5542 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5543 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5544 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5547 // Leaving those out was a mistake, those were in the old code, and they
5548 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5549 // I couldn't reproduce it after adding those normalizations. --blub
5550 VectorNormalize(r_refdef.view.frustum[0].normal);
5551 VectorNormalize(r_refdef.view.frustum[1].normal);
5552 VectorNormalize(r_refdef.view.frustum[2].normal);
5553 VectorNormalize(r_refdef.view.frustum[3].normal);
5555 // make the corners absolute
5556 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5557 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5558 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5559 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5562 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5564 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5565 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5566 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5567 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5568 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5572 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5573 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5574 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5575 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5576 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5577 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5578 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5579 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5580 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5581 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5583 r_refdef.view.numfrustumplanes = 5;
5585 if (r_refdef.view.useclipplane)
5587 r_refdef.view.numfrustumplanes = 6;
5588 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5591 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5592 PlaneClassify(r_refdef.view.frustum + i);
5594 // LordHavoc: note to all quake engine coders, Quake had a special case
5595 // for 90 degrees which assumed a square view (wrong), so I removed it,
5596 // Quake2 has it disabled as well.
5598 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5599 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5600 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5601 //PlaneClassify(&frustum[0]);
5603 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5604 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5605 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5606 //PlaneClassify(&frustum[1]);
5608 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5609 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5610 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5611 //PlaneClassify(&frustum[2]);
5613 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5614 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5615 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5616 //PlaneClassify(&frustum[3]);
5619 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5620 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5621 //PlaneClassify(&frustum[4]);
5624 static void R_View_UpdateWithScissor(const int *myscissor)
5626 R_Main_ResizeViewCache();
5627 R_View_SetFrustum(myscissor);
5628 R_View_WorldVisibility(r_refdef.view.useclipplane);
5629 R_View_UpdateEntityVisible();
5630 R_View_UpdateEntityLighting();
5633 static void R_View_Update(void)
5635 R_Main_ResizeViewCache();
5636 R_View_SetFrustum(NULL);
5637 R_View_WorldVisibility(r_refdef.view.useclipplane);
5638 R_View_UpdateEntityVisible();
5639 R_View_UpdateEntityLighting();
5642 float viewscalefpsadjusted = 1.0f;
5644 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5646 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5647 scale = bound(0.03125f, scale, 1.0f);
5648 *outwidth = (int)ceil(width * scale);
5649 *outheight = (int)ceil(height * scale);
5652 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5654 const float *customclipplane = NULL;
5656 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5657 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5659 // LordHavoc: couldn't figure out how to make this approach the
5660 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5661 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5662 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5663 dist = r_refdef.view.clipplane.dist;
5664 plane[0] = r_refdef.view.clipplane.normal[0];
5665 plane[1] = r_refdef.view.clipplane.normal[1];
5666 plane[2] = r_refdef.view.clipplane.normal[2];
5668 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5671 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5672 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5674 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5675 if (!r_refdef.view.useperspective)
5676 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);
5677 else if (vid.stencil && r_useinfinitefarclip.integer)
5678 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);
5680 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);
5681 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5682 R_SetViewport(&r_refdef.view.viewport);
5683 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5685 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5686 float screenplane[4];
5687 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5688 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5689 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5690 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5691 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5695 void R_EntityMatrix(const matrix4x4_t *matrix)
5697 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5699 gl_modelmatrixchanged = false;
5700 gl_modelmatrix = *matrix;
5701 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5702 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5703 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5704 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5706 switch(vid.renderpath)
5708 case RENDERPATH_D3D9:
5710 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5711 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5714 case RENDERPATH_D3D10:
5715 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5717 case RENDERPATH_D3D11:
5718 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5720 case RENDERPATH_GL11:
5721 case RENDERPATH_GL13:
5722 case RENDERPATH_GLES1:
5724 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5727 case RENDERPATH_SOFT:
5728 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5729 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5731 case RENDERPATH_GL20:
5732 case RENDERPATH_GLES2:
5733 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5734 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5740 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5742 r_viewport_t viewport;
5746 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5747 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);
5748 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5749 R_SetViewport(&viewport);
5750 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5751 GL_Color(1, 1, 1, 1);
5752 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5753 GL_BlendFunc(GL_ONE, GL_ZERO);
5754 GL_ScissorTest(false);
5755 GL_DepthMask(false);
5756 GL_DepthRange(0, 1);
5757 GL_DepthTest(false);
5758 GL_DepthFunc(GL_LEQUAL);
5759 R_EntityMatrix(&identitymatrix);
5760 R_Mesh_ResetTextureState();
5761 GL_PolygonOffset(0, 0);
5762 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5763 switch(vid.renderpath)
5765 case RENDERPATH_GL11:
5766 case RENDERPATH_GL13:
5767 case RENDERPATH_GL20:
5768 case RENDERPATH_GLES1:
5769 case RENDERPATH_GLES2:
5770 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5772 case RENDERPATH_D3D9:
5773 case RENDERPATH_D3D10:
5774 case RENDERPATH_D3D11:
5775 case RENDERPATH_SOFT:
5778 GL_CullFace(GL_NONE);
5783 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5787 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5790 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5794 R_SetupView(true, fbo, depthtexture, colortexture);
5795 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5796 GL_Color(1, 1, 1, 1);
5797 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5798 GL_BlendFunc(GL_ONE, GL_ZERO);
5799 GL_ScissorTest(true);
5801 GL_DepthRange(0, 1);
5803 GL_DepthFunc(GL_LEQUAL);
5804 R_EntityMatrix(&identitymatrix);
5805 R_Mesh_ResetTextureState();
5806 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5807 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5808 switch(vid.renderpath)
5810 case RENDERPATH_GL11:
5811 case RENDERPATH_GL13:
5812 case RENDERPATH_GL20:
5813 case RENDERPATH_GLES1:
5814 case RENDERPATH_GLES2:
5815 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5817 case RENDERPATH_D3D9:
5818 case RENDERPATH_D3D10:
5819 case RENDERPATH_D3D11:
5820 case RENDERPATH_SOFT:
5823 GL_CullFace(r_refdef.view.cullface_back);
5828 R_RenderView_UpdateViewVectors
5831 void R_RenderView_UpdateViewVectors(void)
5833 // break apart the view matrix into vectors for various purposes
5834 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5835 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5836 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5837 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5838 // make an inverted copy of the view matrix for tracking sprites
5839 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5842 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5843 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5845 static void R_Water_StartFrame(void)
5848 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5849 r_waterstate_waterplane_t *p;
5850 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;
5852 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5855 switch(vid.renderpath)
5857 case RENDERPATH_GL20:
5858 case RENDERPATH_D3D9:
5859 case RENDERPATH_D3D10:
5860 case RENDERPATH_D3D11:
5861 case RENDERPATH_SOFT:
5862 case RENDERPATH_GLES2:
5864 case RENDERPATH_GL11:
5865 case RENDERPATH_GL13:
5866 case RENDERPATH_GLES1:
5870 // set waterwidth and waterheight to the water resolution that will be
5871 // used (often less than the screen resolution for faster rendering)
5872 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5874 // calculate desired texture sizes
5875 // can't use water if the card does not support the texture size
5876 if (!r_water.integer || r_showsurfaces.integer)
5877 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5878 else if (vid.support.arb_texture_non_power_of_two)
5880 texturewidth = waterwidth;
5881 textureheight = waterheight;
5882 camerawidth = waterwidth;
5883 cameraheight = waterheight;
5887 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5888 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5889 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5890 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5893 // allocate textures as needed
5894 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))
5896 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5897 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5899 if (p->texture_refraction)
5900 R_FreeTexture(p->texture_refraction);
5901 p->texture_refraction = NULL;
5902 if (p->fbo_refraction)
5903 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5904 p->fbo_refraction = 0;
5905 if (p->texture_reflection)
5906 R_FreeTexture(p->texture_reflection);
5907 p->texture_reflection = NULL;
5908 if (p->fbo_reflection)
5909 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5910 p->fbo_reflection = 0;
5911 if (p->texture_camera)
5912 R_FreeTexture(p->texture_camera);
5913 p->texture_camera = NULL;
5915 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5918 memset(&r_fb.water, 0, sizeof(r_fb.water));
5919 r_fb.water.texturewidth = texturewidth;
5920 r_fb.water.textureheight = textureheight;
5921 r_fb.water.camerawidth = camerawidth;
5922 r_fb.water.cameraheight = cameraheight;
5925 if (r_fb.water.texturewidth)
5927 int scaledwidth, scaledheight;
5929 r_fb.water.enabled = true;
5931 // water resolution is usually reduced
5932 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5933 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5934 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5936 // set up variables that will be used in shader setup
5937 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5938 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5939 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5940 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5943 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5944 r_fb.water.numwaterplanes = 0;
5947 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5949 int planeindex, bestplaneindex, vertexindex;
5950 vec3_t mins, maxs, normal, center, v, n;
5951 vec_t planescore, bestplanescore;
5953 r_waterstate_waterplane_t *p;
5954 texture_t *t = R_GetCurrentTexture(surface->texture);
5956 rsurface.texture = t;
5957 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5958 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5959 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5961 // average the vertex normals, find the surface bounds (after deformvertexes)
5962 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5963 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5964 VectorCopy(n, normal);
5965 VectorCopy(v, mins);
5966 VectorCopy(v, maxs);
5967 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5969 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5970 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5971 VectorAdd(normal, n, normal);
5972 mins[0] = min(mins[0], v[0]);
5973 mins[1] = min(mins[1], v[1]);
5974 mins[2] = min(mins[2], v[2]);
5975 maxs[0] = max(maxs[0], v[0]);
5976 maxs[1] = max(maxs[1], v[1]);
5977 maxs[2] = max(maxs[2], v[2]);
5979 VectorNormalize(normal);
5980 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5982 VectorCopy(normal, plane.normal);
5983 VectorNormalize(plane.normal);
5984 plane.dist = DotProduct(center, plane.normal);
5985 PlaneClassify(&plane);
5986 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5988 // skip backfaces (except if nocullface is set)
5989 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5991 VectorNegate(plane.normal, plane.normal);
5993 PlaneClassify(&plane);
5997 // find a matching plane if there is one
5998 bestplaneindex = -1;
5999 bestplanescore = 1048576.0f;
6000 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6002 if(p->camera_entity == t->camera_entity)
6004 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6005 if (bestplaneindex < 0 || bestplanescore > planescore)
6007 bestplaneindex = planeindex;
6008 bestplanescore = planescore;
6012 planeindex = bestplaneindex;
6014 // if this surface does not fit any known plane rendered this frame, add one
6015 if (planeindex < 0 || bestplanescore > 0.001f)
6017 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6019 // store the new plane
6020 planeindex = r_fb.water.numwaterplanes++;
6021 p = r_fb.water.waterplanes + planeindex;
6023 // clear materialflags and pvs
6024 p->materialflags = 0;
6025 p->pvsvalid = false;
6026 p->camera_entity = t->camera_entity;
6027 VectorCopy(mins, p->mins);
6028 VectorCopy(maxs, p->maxs);
6032 // We're totally screwed.
6038 // merge mins/maxs when we're adding this surface to the plane
6039 p = r_fb.water.waterplanes + planeindex;
6040 p->mins[0] = min(p->mins[0], mins[0]);
6041 p->mins[1] = min(p->mins[1], mins[1]);
6042 p->mins[2] = min(p->mins[2], mins[2]);
6043 p->maxs[0] = max(p->maxs[0], maxs[0]);
6044 p->maxs[1] = max(p->maxs[1], maxs[1]);
6045 p->maxs[2] = max(p->maxs[2], maxs[2]);
6047 // merge this surface's materialflags into the waterplane
6048 p->materialflags |= t->currentmaterialflags;
6049 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6051 // merge this surface's PVS into the waterplane
6052 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6053 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6055 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6061 extern cvar_t r_drawparticles;
6062 extern cvar_t r_drawdecals;
6064 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6067 r_refdef_view_t originalview;
6068 r_refdef_view_t myview;
6069 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;
6070 r_waterstate_waterplane_t *p;
6072 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;
6075 originalview = r_refdef.view;
6077 // lowquality hack, temporarily shut down some cvars and restore afterwards
6078 qualityreduction = r_water_lowquality.integer;
6079 if (qualityreduction > 0)
6081 if (qualityreduction >= 1)
6083 old_r_shadows = r_shadows.integer;
6084 old_r_worldrtlight = r_shadow_realtime_world.integer;
6085 old_r_dlight = r_shadow_realtime_dlight.integer;
6086 Cvar_SetValueQuick(&r_shadows, 0);
6087 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6088 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6090 if (qualityreduction >= 2)
6092 old_r_dynamic = r_dynamic.integer;
6093 old_r_particles = r_drawparticles.integer;
6094 old_r_decals = r_drawdecals.integer;
6095 Cvar_SetValueQuick(&r_dynamic, 0);
6096 Cvar_SetValueQuick(&r_drawparticles, 0);
6097 Cvar_SetValueQuick(&r_drawdecals, 0);
6101 // make sure enough textures are allocated
6102 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6104 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6106 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6108 if (!p->texture_refraction)
6109 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);
6110 if (!p->texture_refraction)
6114 if (r_fb.water.depthtexture == NULL)
6115 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6116 if (p->fbo_refraction == 0)
6117 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6120 else if (p->materialflags & MATERIALFLAG_CAMERA)
6122 if (!p->texture_camera)
6123 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);
6124 if (!p->texture_camera)
6128 if (r_fb.water.depthtexture == NULL)
6129 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6130 if (p->fbo_camera == 0)
6131 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6135 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6137 if (!p->texture_reflection)
6138 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);
6139 if (!p->texture_reflection)
6143 if (r_fb.water.depthtexture == NULL)
6144 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6145 if (p->fbo_reflection == 0)
6146 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6152 r_refdef.view = originalview;
6153 r_refdef.view.showdebug = false;
6154 r_refdef.view.width = r_fb.water.waterwidth;
6155 r_refdef.view.height = r_fb.water.waterheight;
6156 r_refdef.view.useclipplane = true;
6157 myview = r_refdef.view;
6158 r_fb.water.renderingscene = true;
6159 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6161 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6163 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6165 r_refdef.view = myview;
6166 if(r_water_scissormode.integer)
6168 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6169 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6170 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6173 // render reflected scene and copy into texture
6174 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6175 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6176 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6177 r_refdef.view.clipplane = p->plane;
6178 // reverse the cullface settings for this render
6179 r_refdef.view.cullface_front = GL_FRONT;
6180 r_refdef.view.cullface_back = GL_BACK;
6181 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6183 r_refdef.view.usecustompvs = true;
6185 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6187 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6190 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6191 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6192 R_ClearScreen(r_refdef.fogenabled);
6193 if(r_water_scissormode.integer & 2)
6194 R_View_UpdateWithScissor(myscissor);
6197 R_AnimCache_CacheVisibleEntities();
6198 if(r_water_scissormode.integer & 1)
6199 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6200 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6202 if (!p->fbo_reflection)
6203 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);
6204 r_fb.water.hideplayer = false;
6207 // render the normal view scene and copy into texture
6208 // (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)
6209 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6211 r_refdef.view = myview;
6212 if(r_water_scissormode.integer)
6214 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6215 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6216 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6219 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6221 r_refdef.view.clipplane = p->plane;
6222 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6223 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6225 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6227 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6228 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6229 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6230 R_RenderView_UpdateViewVectors();
6231 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6233 r_refdef.view.usecustompvs = true;
6234 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);
6238 PlaneClassify(&r_refdef.view.clipplane);
6240 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6241 R_ClearScreen(r_refdef.fogenabled);
6242 if(r_water_scissormode.integer & 2)
6243 R_View_UpdateWithScissor(myscissor);
6246 R_AnimCache_CacheVisibleEntities();
6247 if(r_water_scissormode.integer & 1)
6248 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6249 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6251 if (!p->fbo_refraction)
6252 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);
6253 r_fb.water.hideplayer = false;
6255 else if (p->materialflags & MATERIALFLAG_CAMERA)
6257 r_refdef.view = myview;
6259 r_refdef.view.clipplane = p->plane;
6260 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6261 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6263 r_refdef.view.width = r_fb.water.camerawidth;
6264 r_refdef.view.height = r_fb.water.cameraheight;
6265 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6266 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6267 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6268 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6270 if(p->camera_entity)
6272 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6273 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6276 // note: all of the view is used for displaying... so
6277 // there is no use in scissoring
6279 // reverse the cullface settings for this render
6280 r_refdef.view.cullface_front = GL_FRONT;
6281 r_refdef.view.cullface_back = GL_BACK;
6282 // also reverse the view matrix
6283 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
6284 R_RenderView_UpdateViewVectors();
6285 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6287 r_refdef.view.usecustompvs = true;
6288 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);
6291 // camera needs no clipplane
6292 r_refdef.view.useclipplane = false;
6294 PlaneClassify(&r_refdef.view.clipplane);
6296 r_fb.water.hideplayer = false;
6298 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6299 R_ClearScreen(r_refdef.fogenabled);
6301 R_AnimCache_CacheVisibleEntities();
6302 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6305 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);
6306 r_fb.water.hideplayer = false;
6310 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6311 r_fb.water.renderingscene = false;
6312 r_refdef.view = originalview;
6313 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6314 if (!r_fb.water.depthtexture)
6315 R_ClearScreen(r_refdef.fogenabled);
6317 R_AnimCache_CacheVisibleEntities();
6320 r_refdef.view = originalview;
6321 r_fb.water.renderingscene = false;
6322 Cvar_SetValueQuick(&r_water, 0);
6323 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6325 // lowquality hack, restore cvars
6326 if (qualityreduction > 0)
6328 if (qualityreduction >= 1)
6330 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6331 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6332 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6334 if (qualityreduction >= 2)
6336 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6337 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6338 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6343 static void R_Bloom_StartFrame(void)
6346 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6347 int viewwidth, viewheight;
6348 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6349 textype_t textype = TEXTYPE_COLORBUFFER;
6351 switch (vid.renderpath)
6353 case RENDERPATH_GL20:
6354 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6355 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6357 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6358 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6361 case RENDERPATH_GL11:
6362 case RENDERPATH_GL13:
6363 case RENDERPATH_GLES1:
6364 case RENDERPATH_GLES2:
6365 case RENDERPATH_D3D9:
6366 case RENDERPATH_D3D10:
6367 case RENDERPATH_D3D11:
6368 r_fb.usedepthtextures = false;
6370 case RENDERPATH_SOFT:
6371 r_fb.usedepthtextures = true;
6375 if (r_viewscale_fpsscaling.integer)
6377 double actualframetime;
6378 double targetframetime;
6380 actualframetime = r_refdef.lastdrawscreentime;
6381 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6382 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6383 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6384 if (r_viewscale_fpsscaling_stepsize.value > 0)
6385 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6386 viewscalefpsadjusted += adjust;
6387 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6390 viewscalefpsadjusted = 1.0f;
6392 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6394 switch(vid.renderpath)
6396 case RENDERPATH_GL20:
6397 case RENDERPATH_D3D9:
6398 case RENDERPATH_D3D10:
6399 case RENDERPATH_D3D11:
6400 case RENDERPATH_SOFT:
6401 case RENDERPATH_GLES2:
6403 case RENDERPATH_GL11:
6404 case RENDERPATH_GL13:
6405 case RENDERPATH_GLES1:
6409 // set bloomwidth and bloomheight to the bloom resolution that will be
6410 // used (often less than the screen resolution for faster rendering)
6411 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6412 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6413 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6414 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6415 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6417 // calculate desired texture sizes
6418 if (vid.support.arb_texture_non_power_of_two)
6420 screentexturewidth = vid.width;
6421 screentextureheight = vid.height;
6422 bloomtexturewidth = r_fb.bloomwidth;
6423 bloomtextureheight = r_fb.bloomheight;
6427 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6428 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6429 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6430 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6433 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))
6435 Cvar_SetValueQuick(&r_bloom, 0);
6436 Cvar_SetValueQuick(&r_motionblur, 0);
6437 Cvar_SetValueQuick(&r_damageblur, 0);
6440 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6442 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6444 && r_viewscale.value == 1.0f
6445 && !r_viewscale_fpsscaling.integer)
6446 screentexturewidth = screentextureheight = 0;
6447 if (!r_bloom.integer)
6448 bloomtexturewidth = bloomtextureheight = 0;
6450 // allocate textures as needed
6451 if (r_fb.screentexturewidth != screentexturewidth
6452 || r_fb.screentextureheight != screentextureheight
6453 || r_fb.bloomtexturewidth != bloomtexturewidth
6454 || r_fb.bloomtextureheight != bloomtextureheight
6455 || r_fb.textype != textype
6456 || useviewfbo != (r_fb.fbo != 0))
6458 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6460 if (r_fb.bloomtexture[i])
6461 R_FreeTexture(r_fb.bloomtexture[i]);
6462 r_fb.bloomtexture[i] = NULL;
6464 if (r_fb.bloomfbo[i])
6465 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6466 r_fb.bloomfbo[i] = 0;
6470 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6473 if (r_fb.colortexture)
6474 R_FreeTexture(r_fb.colortexture);
6475 r_fb.colortexture = NULL;
6477 if (r_fb.depthtexture)
6478 R_FreeTexture(r_fb.depthtexture);
6479 r_fb.depthtexture = NULL;
6481 if (r_fb.ghosttexture)
6482 R_FreeTexture(r_fb.ghosttexture);
6483 r_fb.ghosttexture = NULL;
6485 r_fb.screentexturewidth = screentexturewidth;
6486 r_fb.screentextureheight = screentextureheight;
6487 r_fb.bloomtexturewidth = bloomtexturewidth;
6488 r_fb.bloomtextureheight = bloomtextureheight;
6489 r_fb.textype = textype;
6491 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6493 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6494 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);
6495 r_fb.ghosttexture_valid = false;
6496 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);
6499 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6500 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6501 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6505 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6507 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6509 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);
6511 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6516 // bloom texture is a different resolution
6517 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6518 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6519 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6520 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6521 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6523 // set up a texcoord array for the full resolution screen image
6524 // (we have to keep this around to copy back during final render)
6525 r_fb.screentexcoord2f[0] = 0;
6526 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6527 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6528 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6529 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6530 r_fb.screentexcoord2f[5] = 0;
6531 r_fb.screentexcoord2f[6] = 0;
6532 r_fb.screentexcoord2f[7] = 0;
6536 for (i = 1;i < 8;i += 2)
6538 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6542 // set up a texcoord array for the reduced resolution bloom image
6543 // (which will be additive blended over the screen image)
6544 r_fb.bloomtexcoord2f[0] = 0;
6545 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6546 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6547 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6548 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6549 r_fb.bloomtexcoord2f[5] = 0;
6550 r_fb.bloomtexcoord2f[6] = 0;
6551 r_fb.bloomtexcoord2f[7] = 0;
6553 switch(vid.renderpath)
6555 case RENDERPATH_GL11:
6556 case RENDERPATH_GL13:
6557 case RENDERPATH_GL20:
6558 case RENDERPATH_SOFT:
6559 case RENDERPATH_GLES1:
6560 case RENDERPATH_GLES2:
6562 case RENDERPATH_D3D9:
6563 case RENDERPATH_D3D10:
6564 case RENDERPATH_D3D11:
6565 for (i = 0;i < 4;i++)
6567 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6568 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6569 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6570 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6575 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6578 r_refdef.view.clear = true;
6581 static void R_Bloom_MakeTexture(void)
6584 float xoffset, yoffset, r, brighten;
6586 float colorscale = r_bloom_colorscale.value;
6588 r_refdef.stats[r_stat_bloom]++;
6591 // this copy is unnecessary since it happens in R_BlendView already
6594 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);
6595 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6599 // scale down screen texture to the bloom texture size
6601 r_fb.bloomindex = 0;
6602 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6603 R_SetViewport(&r_fb.bloomviewport);
6604 GL_DepthTest(false);
6605 GL_BlendFunc(GL_ONE, GL_ZERO);
6606 GL_Color(colorscale, colorscale, colorscale, 1);
6607 // 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...
6608 switch(vid.renderpath)
6610 case RENDERPATH_GL11:
6611 case RENDERPATH_GL13:
6612 case RENDERPATH_GL20:
6613 case RENDERPATH_GLES1:
6614 case RENDERPATH_GLES2:
6615 case RENDERPATH_SOFT:
6616 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6618 case RENDERPATH_D3D9:
6619 case RENDERPATH_D3D10:
6620 case RENDERPATH_D3D11:
6621 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6624 // TODO: do boxfilter scale-down in shader?
6625 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6626 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6627 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6629 // we now have a properly scaled bloom image
6630 if (!r_fb.bloomfbo[r_fb.bloomindex])
6632 // copy it into the bloom texture
6633 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);
6634 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6637 // multiply bloom image by itself as many times as desired
6638 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6640 intex = r_fb.bloomtexture[r_fb.bloomindex];
6641 r_fb.bloomindex ^= 1;
6642 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6644 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6645 if (!r_fb.bloomfbo[r_fb.bloomindex])
6647 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6648 GL_Color(r,r,r,1); // apply fix factor
6653 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6654 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6655 GL_Color(1,1,1,1); // no fix factor supported here
6657 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6658 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6659 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6660 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6662 if (!r_fb.bloomfbo[r_fb.bloomindex])
6664 // copy the darkened image to a texture
6665 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);
6666 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6670 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6671 brighten = r_bloom_brighten.value;
6672 brighten = sqrt(brighten);
6674 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6676 for (dir = 0;dir < 2;dir++)
6678 intex = r_fb.bloomtexture[r_fb.bloomindex];
6679 r_fb.bloomindex ^= 1;
6680 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6681 // blend on at multiple vertical offsets to achieve a vertical blur
6682 // TODO: do offset blends using GLSL
6683 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6684 GL_BlendFunc(GL_ONE, GL_ZERO);
6685 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6686 for (x = -range;x <= range;x++)
6688 if (!dir){xoffset = 0;yoffset = x;}
6689 else {xoffset = x;yoffset = 0;}
6690 xoffset /= (float)r_fb.bloomtexturewidth;
6691 yoffset /= (float)r_fb.bloomtextureheight;
6692 // compute a texcoord array with the specified x and y offset
6693 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6694 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6695 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6696 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6697 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6698 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6699 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6700 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6701 // this r value looks like a 'dot' particle, fading sharply to
6702 // black at the edges
6703 // (probably not realistic but looks good enough)
6704 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6705 //r = brighten/(range*2+1);
6706 r = brighten / (range * 2 + 1);
6708 r *= (1 - x*x/(float)(range*range));
6709 GL_Color(r, r, r, 1);
6710 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6711 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6712 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6713 GL_BlendFunc(GL_ONE, GL_ONE);
6716 if (!r_fb.bloomfbo[r_fb.bloomindex])
6718 // copy the vertically or horizontally blurred bloom view to a texture
6719 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);
6720 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6725 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6727 unsigned int permutation;
6728 float uservecs[4][4];
6730 R_EntityMatrix(&identitymatrix);
6732 switch (vid.renderpath)
6734 case RENDERPATH_GL20:
6735 case RENDERPATH_D3D9:
6736 case RENDERPATH_D3D10:
6737 case RENDERPATH_D3D11:
6738 case RENDERPATH_SOFT:
6739 case RENDERPATH_GLES2:
6741 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6742 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6743 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6744 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6745 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6747 if (r_fb.colortexture)
6751 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);
6752 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6755 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6757 // declare variables
6758 float blur_factor, blur_mouseaccel, blur_velocity;
6759 static float blur_average;
6760 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6762 // set a goal for the factoring
6763 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6764 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6765 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6766 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6767 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6768 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6770 // from the goal, pick an averaged value between goal and last value
6771 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6772 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6774 // enforce minimum amount of blur
6775 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6777 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6779 // calculate values into a standard alpha
6780 cl.motionbluralpha = 1 - exp(-
6782 (r_motionblur.value * blur_factor / 80)
6784 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6787 max(0.0001, cl.time - cl.oldtime) // fps independent
6790 // randomization for the blur value to combat persistent ghosting
6791 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6792 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6795 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6796 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6798 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6799 GL_Color(1, 1, 1, cl.motionbluralpha);
6800 switch(vid.renderpath)
6802 case RENDERPATH_GL11:
6803 case RENDERPATH_GL13:
6804 case RENDERPATH_GL20:
6805 case RENDERPATH_GLES1:
6806 case RENDERPATH_GLES2:
6807 case RENDERPATH_SOFT:
6808 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6810 case RENDERPATH_D3D9:
6811 case RENDERPATH_D3D10:
6812 case RENDERPATH_D3D11:
6813 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6816 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6817 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6818 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6821 // updates old view angles for next pass
6822 VectorCopy(cl.viewangles, blur_oldangles);
6824 // copy view into the ghost texture
6825 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);
6826 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6827 r_fb.ghosttexture_valid = true;
6832 // no r_fb.colortexture means we're rendering to the real fb
6833 // we may still have to do view tint...
6834 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6836 // apply a color tint to the whole view
6837 R_ResetViewRendering2D(0, NULL, NULL);
6838 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6839 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6840 R_SetupShader_Generic_NoTexture(false, true);
6841 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6842 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6844 break; // no screen processing, no bloom, skip it
6847 if (r_fb.bloomtexture[0])
6849 // make the bloom texture
6850 R_Bloom_MakeTexture();
6853 #if _MSC_VER >= 1400
6854 #define sscanf sscanf_s
6856 memset(uservecs, 0, sizeof(uservecs));
6857 if (r_glsl_postprocess_uservec1_enable.integer)
6858 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6859 if (r_glsl_postprocess_uservec2_enable.integer)
6860 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6861 if (r_glsl_postprocess_uservec3_enable.integer)
6862 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6863 if (r_glsl_postprocess_uservec4_enable.integer)
6864 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6866 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6867 GL_Color(1, 1, 1, 1);
6868 GL_BlendFunc(GL_ONE, GL_ZERO);
6870 switch(vid.renderpath)
6872 case RENDERPATH_GL20:
6873 case RENDERPATH_GLES2:
6874 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6875 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6876 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6877 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6878 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6879 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]);
6880 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6881 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]);
6882 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]);
6883 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]);
6884 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]);
6885 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6886 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6887 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);
6889 case RENDERPATH_D3D9:
6891 // 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...
6892 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6893 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6894 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6895 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6896 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6897 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6898 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6899 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6900 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6901 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6902 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6903 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6904 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6905 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6908 case RENDERPATH_D3D10:
6909 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6911 case RENDERPATH_D3D11:
6912 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6914 case RENDERPATH_SOFT:
6915 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6916 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6917 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6918 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6919 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6920 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6921 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6922 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6923 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6924 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6925 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6926 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6927 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6928 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6933 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6934 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6936 case RENDERPATH_GL11:
6937 case RENDERPATH_GL13:
6938 case RENDERPATH_GLES1:
6939 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6941 // apply a color tint to the whole view
6942 R_ResetViewRendering2D(0, NULL, NULL);
6943 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6944 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6945 R_SetupShader_Generic_NoTexture(false, true);
6946 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6947 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6953 matrix4x4_t r_waterscrollmatrix;
6955 void R_UpdateFog(void)
6958 if (gamemode == GAME_NEHAHRA)
6960 if (gl_fogenable.integer)
6962 r_refdef.oldgl_fogenable = true;
6963 r_refdef.fog_density = gl_fogdensity.value;
6964 r_refdef.fog_red = gl_fogred.value;
6965 r_refdef.fog_green = gl_foggreen.value;
6966 r_refdef.fog_blue = gl_fogblue.value;
6967 r_refdef.fog_alpha = 1;
6968 r_refdef.fog_start = 0;
6969 r_refdef.fog_end = gl_skyclip.value;
6970 r_refdef.fog_height = 1<<30;
6971 r_refdef.fog_fadedepth = 128;
6973 else if (r_refdef.oldgl_fogenable)
6975 r_refdef.oldgl_fogenable = false;
6976 r_refdef.fog_density = 0;
6977 r_refdef.fog_red = 0;
6978 r_refdef.fog_green = 0;
6979 r_refdef.fog_blue = 0;
6980 r_refdef.fog_alpha = 0;
6981 r_refdef.fog_start = 0;
6982 r_refdef.fog_end = 0;
6983 r_refdef.fog_height = 1<<30;
6984 r_refdef.fog_fadedepth = 128;
6989 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6990 r_refdef.fog_start = max(0, r_refdef.fog_start);
6991 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6993 if (r_refdef.fog_density && r_drawfog.integer)
6995 r_refdef.fogenabled = true;
6996 // this is the point where the fog reaches 0.9986 alpha, which we
6997 // consider a good enough cutoff point for the texture
6998 // (0.9986 * 256 == 255.6)
6999 if (r_fog_exp2.integer)
7000 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7002 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7003 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7004 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7005 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7006 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7007 R_BuildFogHeightTexture();
7008 // fog color was already set
7009 // update the fog texture
7010 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)
7011 R_BuildFogTexture();
7012 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7013 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7016 r_refdef.fogenabled = false;
7019 if (r_refdef.fog_density)
7021 r_refdef.fogcolor[0] = r_refdef.fog_red;
7022 r_refdef.fogcolor[1] = r_refdef.fog_green;
7023 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7025 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7026 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7027 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7028 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7032 VectorCopy(r_refdef.fogcolor, fogvec);
7033 // color.rgb *= ContrastBoost * SceneBrightness;
7034 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7035 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7036 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7037 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7042 void R_UpdateVariables(void)
7046 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7048 r_refdef.farclip = r_farclip_base.value;
7049 if (r_refdef.scene.worldmodel)
7050 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7051 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7053 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7054 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7055 r_refdef.polygonfactor = 0;
7056 r_refdef.polygonoffset = 0;
7057 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7058 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7060 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7061 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7062 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7063 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7064 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7065 if (FAKELIGHT_ENABLED)
7067 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7069 else if (r_refdef.scene.worldmodel)
7071 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7073 if (r_showsurfaces.integer)
7075 r_refdef.scene.rtworld = false;
7076 r_refdef.scene.rtworldshadows = false;
7077 r_refdef.scene.rtdlight = false;
7078 r_refdef.scene.rtdlightshadows = false;
7079 r_refdef.lightmapintensity = 0;
7082 r_gpuskeletal = false;
7083 switch(vid.renderpath)
7085 case RENDERPATH_GL20:
7086 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7087 case RENDERPATH_D3D9:
7088 case RENDERPATH_D3D10:
7089 case RENDERPATH_D3D11:
7090 case RENDERPATH_SOFT:
7091 case RENDERPATH_GLES2:
7092 if(v_glslgamma.integer && !vid_gammatables_trivial)
7094 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7096 // build GLSL gamma texture
7097 #define RAMPWIDTH 256
7098 unsigned short ramp[RAMPWIDTH * 3];
7099 unsigned char rampbgr[RAMPWIDTH][4];
7102 r_texture_gammaramps_serial = vid_gammatables_serial;
7104 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7105 for(i = 0; i < RAMPWIDTH; ++i)
7107 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7108 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7109 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7112 if (r_texture_gammaramps)
7114 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7118 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7124 // remove GLSL gamma texture
7127 case RENDERPATH_GL11:
7128 case RENDERPATH_GL13:
7129 case RENDERPATH_GLES1:
7134 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7135 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7141 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7142 if( scenetype != r_currentscenetype ) {
7143 // store the old scenetype
7144 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7145 r_currentscenetype = scenetype;
7146 // move in the new scene
7147 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7156 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7158 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7159 if( scenetype == r_currentscenetype ) {
7160 return &r_refdef.scene;
7162 return &r_scenes_store[ scenetype ];
7166 static int R_SortEntities_Compare(const void *ap, const void *bp)
7168 const entity_render_t *a = *(const entity_render_t **)ap;
7169 const entity_render_t *b = *(const entity_render_t **)bp;
7172 if(a->model < b->model)
7174 if(a->model > b->model)
7178 // TODO possibly calculate the REAL skinnum here first using
7180 if(a->skinnum < b->skinnum)
7182 if(a->skinnum > b->skinnum)
7185 // everything we compared is equal
7188 static void R_SortEntities(void)
7190 // below or equal 2 ents, sorting never gains anything
7191 if(r_refdef.scene.numentities <= 2)
7194 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7202 int dpsoftrast_test;
7203 extern cvar_t r_shadow_bouncegrid;
7204 void R_RenderView(void)
7206 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7208 rtexture_t *depthtexture;
7209 rtexture_t *colortexture;
7211 dpsoftrast_test = r_test.integer;
7213 if (r_timereport_active)
7214 R_TimeReport("start");
7215 r_textureframe++; // used only by R_GetCurrentTexture
7216 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7218 if(R_CompileShader_CheckStaticParms())
7221 if (!r_drawentities.integer)
7222 r_refdef.scene.numentities = 0;
7223 else if (r_sortentities.integer)
7226 R_AnimCache_ClearCache();
7228 /* adjust for stereo display */
7229 if(R_Stereo_Active())
7231 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);
7232 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7235 if (r_refdef.view.isoverlay)
7237 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7238 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7239 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7240 R_TimeReport("depthclear");
7242 r_refdef.view.showdebug = false;
7244 r_fb.water.enabled = false;
7245 r_fb.water.numwaterplanes = 0;
7247 R_RenderScene(0, NULL, NULL);
7249 r_refdef.view.matrix = originalmatrix;
7255 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7257 r_refdef.view.matrix = originalmatrix;
7261 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7263 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7264 // in sRGB fallback, behave similar to true sRGB: convert this
7265 // value from linear to sRGB
7266 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7268 R_RenderView_UpdateViewVectors();
7270 R_Shadow_UpdateWorldLightSelection();
7272 R_Bloom_StartFrame();
7274 // apply bloom brightness offset
7275 if(r_fb.bloomtexture[0])
7276 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7278 R_Water_StartFrame();
7280 // now we probably have an fbo to render into
7282 depthtexture = r_fb.depthtexture;
7283 colortexture = r_fb.colortexture;
7286 if (r_timereport_active)
7287 R_TimeReport("viewsetup");
7289 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7291 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7293 R_ClearScreen(r_refdef.fogenabled);
7294 if (r_timereport_active)
7295 R_TimeReport("viewclear");
7297 r_refdef.view.clear = true;
7299 r_refdef.view.showdebug = true;
7302 if (r_timereport_active)
7303 R_TimeReport("visibility");
7305 R_AnimCache_CacheVisibleEntities();
7306 if (r_timereport_active)
7307 R_TimeReport("animcache");
7309 R_Shadow_UpdateBounceGridTexture();
7310 if (r_timereport_active && r_shadow_bouncegrid.integer)
7311 R_TimeReport("bouncegrid");
7313 r_fb.water.numwaterplanes = 0;
7314 if (r_fb.water.enabled)
7315 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7317 R_RenderScene(fbo, depthtexture, colortexture);
7318 r_fb.water.numwaterplanes = 0;
7320 R_BlendView(fbo, depthtexture, colortexture);
7321 if (r_timereport_active)
7322 R_TimeReport("blendview");
7324 GL_Scissor(0, 0, vid.width, vid.height);
7325 GL_ScissorTest(false);
7327 r_refdef.view.matrix = originalmatrix;
7332 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7334 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7336 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7337 if (r_timereport_active)
7338 R_TimeReport("waterworld");
7341 // don't let sound skip if going slow
7342 if (r_refdef.scene.extraupdate)
7345 R_DrawModelsAddWaterPlanes();
7346 if (r_timereport_active)
7347 R_TimeReport("watermodels");
7349 if (r_fb.water.numwaterplanes)
7351 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7352 if (r_timereport_active)
7353 R_TimeReport("waterscenes");
7357 extern cvar_t cl_locs_show;
7358 static void R_DrawLocs(void);
7359 static void R_DrawEntityBBoxes(void);
7360 static void R_DrawModelDecals(void);
7361 extern cvar_t cl_decals_newsystem;
7362 extern qboolean r_shadow_usingdeferredprepass;
7363 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7365 qboolean shadowmapping = false;
7367 if (r_timereport_active)
7368 R_TimeReport("beginscene");
7370 r_refdef.stats[r_stat_renders]++;
7374 // don't let sound skip if going slow
7375 if (r_refdef.scene.extraupdate)
7378 R_MeshQueue_BeginScene();
7382 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);
7384 if (r_timereport_active)
7385 R_TimeReport("skystartframe");
7387 if (cl.csqc_vidvars.drawworld)
7389 // don't let sound skip if going slow
7390 if (r_refdef.scene.extraupdate)
7393 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7395 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7396 if (r_timereport_active)
7397 R_TimeReport("worldsky");
7400 if (R_DrawBrushModelsSky() && r_timereport_active)
7401 R_TimeReport("bmodelsky");
7403 if (skyrendermasked && skyrenderlater)
7405 // we have to force off the water clipping plane while rendering sky
7406 R_SetupView(false, fbo, depthtexture, colortexture);
7408 R_SetupView(true, fbo, depthtexture, colortexture);
7409 if (r_timereport_active)
7410 R_TimeReport("sky");
7414 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7415 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7416 R_Shadow_PrepareModelShadows();
7417 if (r_timereport_active)
7418 R_TimeReport("preparelights");
7420 if (R_Shadow_ShadowMappingEnabled())
7421 shadowmapping = true;
7423 if (r_shadow_usingdeferredprepass)
7424 R_Shadow_DrawPrepass();
7426 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7428 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7429 if (r_timereport_active)
7430 R_TimeReport("worlddepth");
7432 if (r_depthfirst.integer >= 2)
7434 R_DrawModelsDepth();
7435 if (r_timereport_active)
7436 R_TimeReport("modeldepth");
7439 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7441 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7442 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7443 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7444 // don't let sound skip if going slow
7445 if (r_refdef.scene.extraupdate)
7449 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7451 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7452 if (r_timereport_active)
7453 R_TimeReport("world");
7456 // don't let sound skip if going slow
7457 if (r_refdef.scene.extraupdate)
7461 if (r_timereport_active)
7462 R_TimeReport("models");
7464 // don't let sound skip if going slow
7465 if (r_refdef.scene.extraupdate)
7468 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7470 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7471 R_DrawModelShadows(fbo, depthtexture, colortexture);
7472 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7473 // don't let sound skip if going slow
7474 if (r_refdef.scene.extraupdate)
7478 if (!r_shadow_usingdeferredprepass)
7480 R_Shadow_DrawLights();
7481 if (r_timereport_active)
7482 R_TimeReport("rtlights");
7485 // don't let sound skip if going slow
7486 if (r_refdef.scene.extraupdate)
7489 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7491 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7492 R_DrawModelShadows(fbo, depthtexture, colortexture);
7493 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7494 // don't let sound skip if going slow
7495 if (r_refdef.scene.extraupdate)
7499 if (cl.csqc_vidvars.drawworld)
7501 if (cl_decals_newsystem.integer)
7503 R_DrawModelDecals();
7504 if (r_timereport_active)
7505 R_TimeReport("modeldecals");
7510 if (r_timereport_active)
7511 R_TimeReport("decals");
7515 if (r_timereport_active)
7516 R_TimeReport("particles");
7519 if (r_timereport_active)
7520 R_TimeReport("explosions");
7522 R_DrawLightningBeams();
7523 if (r_timereport_active)
7524 R_TimeReport("lightning");
7528 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7530 if (r_refdef.view.showdebug)
7532 if (cl_locs_show.integer)
7535 if (r_timereport_active)
7536 R_TimeReport("showlocs");
7539 if (r_drawportals.integer)
7542 if (r_timereport_active)
7543 R_TimeReport("portals");
7546 if (r_showbboxes.value > 0)
7548 R_DrawEntityBBoxes();
7549 if (r_timereport_active)
7550 R_TimeReport("bboxes");
7554 if (r_transparent.integer)
7556 R_MeshQueue_RenderTransparent();
7557 if (r_timereport_active)
7558 R_TimeReport("drawtrans");
7561 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))
7563 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7564 if (r_timereport_active)
7565 R_TimeReport("worlddebug");
7566 R_DrawModelsDebug();
7567 if (r_timereport_active)
7568 R_TimeReport("modeldebug");
7571 if (cl.csqc_vidvars.drawworld)
7573 R_Shadow_DrawCoronas();
7574 if (r_timereport_active)
7575 R_TimeReport("coronas");
7580 GL_DepthTest(false);
7581 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7582 GL_Color(1, 1, 1, 1);
7583 qglBegin(GL_POLYGON);
7584 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7585 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7586 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7587 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7589 qglBegin(GL_POLYGON);
7590 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]);
7591 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]);
7592 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]);
7593 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]);
7595 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7599 // don't let sound skip if going slow
7600 if (r_refdef.scene.extraupdate)
7604 static const unsigned short bboxelements[36] =
7614 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7617 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7619 RSurf_ActiveWorldEntity();
7621 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7622 GL_DepthMask(false);
7623 GL_DepthRange(0, 1);
7624 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7625 // R_Mesh_ResetTextureState();
7627 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7628 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7629 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7630 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7631 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7632 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7633 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7634 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7635 R_FillColors(color4f, 8, cr, cg, cb, ca);
7636 if (r_refdef.fogenabled)
7638 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7640 f1 = RSurf_FogVertex(v);
7642 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7643 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7644 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7647 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7648 R_Mesh_ResetTextureState();
7649 R_SetupShader_Generic_NoTexture(false, false);
7650 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7653 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7655 prvm_prog_t *prog = SVVM_prog;
7658 prvm_edict_t *edict;
7660 // this function draws bounding boxes of server entities
7664 GL_CullFace(GL_NONE);
7665 R_SetupShader_Generic_NoTexture(false, false);
7667 for (i = 0;i < numsurfaces;i++)
7669 edict = PRVM_EDICT_NUM(surfacelist[i]);
7670 switch ((int)PRVM_serveredictfloat(edict, solid))
7672 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7673 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7674 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7675 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7676 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7677 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7678 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7680 color[3] *= r_showbboxes.value;
7681 color[3] = bound(0, color[3], 1);
7682 GL_DepthTest(!r_showdisabledepthtest.integer);
7683 GL_CullFace(r_refdef.view.cullface_front);
7684 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7688 static void R_DrawEntityBBoxes(void)
7691 prvm_edict_t *edict;
7693 prvm_prog_t *prog = SVVM_prog;
7695 // this function draws bounding boxes of server entities
7699 for (i = 0;i < prog->num_edicts;i++)
7701 edict = PRVM_EDICT_NUM(i);
7702 if (edict->priv.server->free)
7704 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7705 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7707 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7709 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7710 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7714 static const int nomodelelement3i[24] =
7726 static const unsigned short nomodelelement3s[24] =
7738 static const float nomodelvertex3f[6*3] =
7748 static const float nomodelcolor4f[6*4] =
7750 0.0f, 0.0f, 0.5f, 1.0f,
7751 0.0f, 0.0f, 0.5f, 1.0f,
7752 0.0f, 0.5f, 0.0f, 1.0f,
7753 0.0f, 0.5f, 0.0f, 1.0f,
7754 0.5f, 0.0f, 0.0f, 1.0f,
7755 0.5f, 0.0f, 0.0f, 1.0f
7758 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7764 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);
7766 // this is only called once per entity so numsurfaces is always 1, and
7767 // surfacelist is always {0}, so this code does not handle batches
7769 if (rsurface.ent_flags & RENDER_ADDITIVE)
7771 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7772 GL_DepthMask(false);
7774 else if (rsurface.colormod[3] < 1)
7776 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7777 GL_DepthMask(false);
7781 GL_BlendFunc(GL_ONE, GL_ZERO);
7784 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7785 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7786 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7787 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7788 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7789 for (i = 0, c = color4f;i < 6;i++, c += 4)
7791 c[0] *= rsurface.colormod[0];
7792 c[1] *= rsurface.colormod[1];
7793 c[2] *= rsurface.colormod[2];
7794 c[3] *= rsurface.colormod[3];
7796 if (r_refdef.fogenabled)
7798 for (i = 0, c = color4f;i < 6;i++, c += 4)
7800 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7802 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7803 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7804 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7807 // R_Mesh_ResetTextureState();
7808 R_SetupShader_Generic_NoTexture(false, false);
7809 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7810 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7813 void R_DrawNoModel(entity_render_t *ent)
7816 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7817 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7818 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7820 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7823 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7825 vec3_t right1, right2, diff, normal;
7827 VectorSubtract (org2, org1, normal);
7829 // calculate 'right' vector for start
7830 VectorSubtract (r_refdef.view.origin, org1, diff);
7831 CrossProduct (normal, diff, right1);
7832 VectorNormalize (right1);
7834 // calculate 'right' vector for end
7835 VectorSubtract (r_refdef.view.origin, org2, diff);
7836 CrossProduct (normal, diff, right2);
7837 VectorNormalize (right2);
7839 vert[ 0] = org1[0] + width * right1[0];
7840 vert[ 1] = org1[1] + width * right1[1];
7841 vert[ 2] = org1[2] + width * right1[2];
7842 vert[ 3] = org1[0] - width * right1[0];
7843 vert[ 4] = org1[1] - width * right1[1];
7844 vert[ 5] = org1[2] - width * right1[2];
7845 vert[ 6] = org2[0] - width * right2[0];
7846 vert[ 7] = org2[1] - width * right2[1];
7847 vert[ 8] = org2[2] - width * right2[2];
7848 vert[ 9] = org2[0] + width * right2[0];
7849 vert[10] = org2[1] + width * right2[1];
7850 vert[11] = org2[2] + width * right2[2];
7853 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)
7855 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7856 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7857 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7858 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7859 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7860 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7861 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7862 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7863 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7864 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7865 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7866 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7869 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7874 VectorSet(v, x, y, z);
7875 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7876 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7878 if (i == mesh->numvertices)
7880 if (mesh->numvertices < mesh->maxvertices)
7882 VectorCopy(v, vertex3f);
7883 mesh->numvertices++;
7885 return mesh->numvertices;
7891 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7895 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7896 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7897 e = mesh->element3i + mesh->numtriangles * 3;
7898 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7900 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7901 if (mesh->numtriangles < mesh->maxtriangles)
7906 mesh->numtriangles++;
7908 element[1] = element[2];
7912 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7916 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7917 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7918 e = mesh->element3i + mesh->numtriangles * 3;
7919 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7921 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7922 if (mesh->numtriangles < mesh->maxtriangles)
7927 mesh->numtriangles++;
7929 element[1] = element[2];
7933 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7934 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7936 int planenum, planenum2;
7939 mplane_t *plane, *plane2;
7941 double temppoints[2][256*3];
7942 // figure out how large a bounding box we need to properly compute this brush
7944 for (w = 0;w < numplanes;w++)
7945 maxdist = max(maxdist, fabs(planes[w].dist));
7946 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7947 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7948 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7952 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7953 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7955 if (planenum2 == planenum)
7957 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);
7960 if (tempnumpoints < 3)
7962 // generate elements forming a triangle fan for this polygon
7963 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7967 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)
7969 texturelayer_t *layer;
7970 layer = t->currentlayers + t->currentnumlayers++;
7972 layer->depthmask = depthmask;
7973 layer->blendfunc1 = blendfunc1;
7974 layer->blendfunc2 = blendfunc2;
7975 layer->texture = texture;
7976 layer->texmatrix = *matrix;
7977 layer->color[0] = r;
7978 layer->color[1] = g;
7979 layer->color[2] = b;
7980 layer->color[3] = a;
7983 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7985 if(parms[0] == 0 && parms[1] == 0)
7987 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7988 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7993 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7996 index = parms[2] + rsurface.shadertime * parms[3];
7997 index -= floor(index);
7998 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8001 case Q3WAVEFUNC_NONE:
8002 case Q3WAVEFUNC_NOISE:
8003 case Q3WAVEFUNC_COUNT:
8006 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8007 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8008 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8009 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8010 case Q3WAVEFUNC_TRIANGLE:
8012 f = index - floor(index);
8025 f = parms[0] + parms[1] * f;
8026 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8027 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8031 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8038 matrix4x4_t matrix, temp;
8039 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8040 // it's better to have one huge fixup every 9 hours than gradual
8041 // degradation over time which looks consistently bad after many hours.
8043 // tcmod scroll in particular suffers from this degradation which can't be
8044 // effectively worked around even with floor() tricks because we don't
8045 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8046 // a workaround involving floor() would be incorrect anyway...
8047 shadertime = rsurface.shadertime;
8048 if (shadertime >= 32768.0f)
8049 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8050 switch(tcmod->tcmod)
8054 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8055 matrix = r_waterscrollmatrix;
8057 matrix = identitymatrix;
8059 case Q3TCMOD_ENTITYTRANSLATE:
8060 // this is used in Q3 to allow the gamecode to control texcoord
8061 // scrolling on the entity, which is not supported in darkplaces yet.
8062 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8064 case Q3TCMOD_ROTATE:
8065 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8066 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8067 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8070 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8072 case Q3TCMOD_SCROLL:
8073 // this particular tcmod is a "bug for bug" compatible one with regards to
8074 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8075 // specifically did the wrapping and so we must mimic that...
8076 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8077 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8078 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8080 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8081 w = (int) tcmod->parms[0];
8082 h = (int) tcmod->parms[1];
8083 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8085 idx = (int) floor(f * w * h);
8086 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8088 case Q3TCMOD_STRETCH:
8089 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8090 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8092 case Q3TCMOD_TRANSFORM:
8093 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8094 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8095 VectorSet(tcmat + 6, 0 , 0 , 1);
8096 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8097 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8099 case Q3TCMOD_TURBULENT:
8100 // this is handled in the RSurf_PrepareVertices function
8101 matrix = identitymatrix;
8105 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8108 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8110 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8111 char name[MAX_QPATH];
8112 skinframe_t *skinframe;
8113 unsigned char pixels[296*194];
8114 strlcpy(cache->name, skinname, sizeof(cache->name));
8115 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8116 if (developer_loading.integer)
8117 Con_Printf("loading %s\n", name);
8118 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8119 if (!skinframe || !skinframe->base)
8122 fs_offset_t filesize;
8124 f = FS_LoadFile(name, tempmempool, true, &filesize);
8127 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8128 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8132 cache->skinframe = skinframe;
8135 texture_t *R_GetCurrentTexture(texture_t *t)
8138 const entity_render_t *ent = rsurface.entity;
8139 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8140 q3shaderinfo_layer_tcmod_t *tcmod;
8142 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8143 return t->currentframe;
8144 t->update_lastrenderframe = r_textureframe;
8145 t->update_lastrenderentity = (void *)ent;
8147 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8148 t->camera_entity = ent->entitynumber;
8150 t->camera_entity = 0;
8152 // switch to an alternate material if this is a q1bsp animated material
8154 texture_t *texture = t;
8155 int s = rsurface.ent_skinnum;
8156 if ((unsigned int)s >= (unsigned int)model->numskins)
8158 if (model->skinscenes)
8160 if (model->skinscenes[s].framecount > 1)
8161 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8163 s = model->skinscenes[s].firstframe;
8166 t = t + s * model->num_surfaces;
8169 // use an alternate animation if the entity's frame is not 0,
8170 // and only if the texture has an alternate animation
8171 if (t->animated == 2) // q2bsp
8172 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8173 else if (rsurface.ent_alttextures && t->anim_total[1])
8174 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8176 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8178 texture->currentframe = t;
8181 // update currentskinframe to be a qw skin or animation frame
8182 if (rsurface.ent_qwskin >= 0)
8184 i = rsurface.ent_qwskin;
8185 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8187 r_qwskincache_size = cl.maxclients;
8189 Mem_Free(r_qwskincache);
8190 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8192 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8193 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8194 t->currentskinframe = r_qwskincache[i].skinframe;
8195 if (t->currentskinframe == NULL)
8196 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8198 else if (t->numskinframes >= 2)
8199 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8200 if (t->backgroundnumskinframes >= 2)
8201 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8203 t->currentmaterialflags = t->basematerialflags;
8204 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8205 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8206 t->currentalpha *= r_wateralpha.value;
8207 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8208 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8209 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8210 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8211 if (!(rsurface.ent_flags & RENDER_LIGHT))
8212 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8213 else if (FAKELIGHT_ENABLED)
8215 // no modellight if using fakelight for the map
8217 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8219 // pick a model lighting mode
8220 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8221 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8223 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8225 if (rsurface.ent_flags & RENDER_ADDITIVE)
8226 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8227 else if (t->currentalpha < 1)
8228 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8229 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8230 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8231 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8232 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8233 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8234 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8235 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8236 if (t->backgroundnumskinframes)
8237 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8238 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8240 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8241 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8244 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8245 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8247 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8248 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8250 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8251 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8253 // there is no tcmod
8254 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8256 t->currenttexmatrix = r_waterscrollmatrix;
8257 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8259 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8261 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8262 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8265 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8266 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8267 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8268 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8270 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8271 if (t->currentskinframe->qpixels)
8272 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8273 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8274 if (!t->basetexture)
8275 t->basetexture = r_texture_notexture;
8276 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8277 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8278 t->nmaptexture = t->currentskinframe->nmap;
8279 if (!t->nmaptexture)
8280 t->nmaptexture = r_texture_blanknormalmap;
8281 t->glosstexture = r_texture_black;
8282 t->glowtexture = t->currentskinframe->glow;
8283 t->fogtexture = t->currentskinframe->fog;
8284 t->reflectmasktexture = t->currentskinframe->reflect;
8285 if (t->backgroundnumskinframes)
8287 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8288 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8289 t->backgroundglosstexture = r_texture_black;
8290 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8291 if (!t->backgroundnmaptexture)
8292 t->backgroundnmaptexture = r_texture_blanknormalmap;
8293 // make sure that if glow is going to be used, both textures are not NULL
8294 if (!t->backgroundglowtexture && t->glowtexture)
8295 t->backgroundglowtexture = r_texture_black;
8296 if (!t->glowtexture && t->backgroundglowtexture)
8297 t->glowtexture = r_texture_black;
8301 t->backgroundbasetexture = r_texture_white;
8302 t->backgroundnmaptexture = r_texture_blanknormalmap;
8303 t->backgroundglosstexture = r_texture_black;
8304 t->backgroundglowtexture = NULL;
8306 t->specularpower = r_shadow_glossexponent.value;
8307 // TODO: store reference values for these in the texture?
8308 t->specularscale = 0;
8309 if (r_shadow_gloss.integer > 0)
8311 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8313 if (r_shadow_glossintensity.value > 0)
8315 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8316 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8317 t->specularscale = r_shadow_glossintensity.value;
8320 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8322 t->glosstexture = r_texture_white;
8323 t->backgroundglosstexture = r_texture_white;
8324 t->specularscale = r_shadow_gloss2intensity.value;
8325 t->specularpower = r_shadow_gloss2exponent.value;
8328 t->specularscale *= t->specularscalemod;
8329 t->specularpower *= t->specularpowermod;
8330 t->rtlightambient = 0;
8332 // lightmaps mode looks bad with dlights using actual texturing, so turn
8333 // off the colormap and glossmap, but leave the normalmap on as it still
8334 // accurately represents the shading involved
8335 if (gl_lightmaps.integer)
8337 t->basetexture = r_texture_grey128;
8338 t->pantstexture = r_texture_black;
8339 t->shirttexture = r_texture_black;
8340 if (gl_lightmaps.integer < 2)
8341 t->nmaptexture = r_texture_blanknormalmap;
8342 t->glosstexture = r_texture_black;
8343 t->glowtexture = NULL;
8344 t->fogtexture = NULL;
8345 t->reflectmasktexture = NULL;
8346 t->backgroundbasetexture = NULL;
8347 if (gl_lightmaps.integer < 2)
8348 t->backgroundnmaptexture = r_texture_blanknormalmap;
8349 t->backgroundglosstexture = r_texture_black;
8350 t->backgroundglowtexture = NULL;
8351 t->specularscale = 0;
8352 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8355 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8356 VectorClear(t->dlightcolor);
8357 t->currentnumlayers = 0;
8358 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8360 int blendfunc1, blendfunc2;
8362 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8364 blendfunc1 = GL_SRC_ALPHA;
8365 blendfunc2 = GL_ONE;
8367 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8369 blendfunc1 = GL_SRC_ALPHA;
8370 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8372 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8374 blendfunc1 = t->customblendfunc[0];
8375 blendfunc2 = t->customblendfunc[1];
8379 blendfunc1 = GL_ONE;
8380 blendfunc2 = GL_ZERO;
8382 // don't colormod evilblend textures
8383 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8384 VectorSet(t->lightmapcolor, 1, 1, 1);
8385 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8386 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8388 // fullbright is not affected by r_refdef.lightmapintensity
8389 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]);
8390 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8391 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]);
8392 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8393 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]);
8397 vec3_t ambientcolor;
8399 // set the color tint used for lights affecting this surface
8400 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8402 // q3bsp has no lightmap updates, so the lightstylevalue that
8403 // would normally be baked into the lightmap must be
8404 // applied to the color
8405 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8406 if (model->type == mod_brushq3)
8407 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8408 colorscale *= r_refdef.lightmapintensity;
8409 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8410 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8411 // basic lit geometry
8412 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]);
8413 // add pants/shirt if needed
8414 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8415 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]);
8416 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8417 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]);
8418 // now add ambient passes if needed
8419 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8421 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]);
8422 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8423 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]);
8424 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8425 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]);
8428 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8429 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]);
8430 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8432 // if this is opaque use alpha blend which will darken the earlier
8435 // if this is an alpha blended material, all the earlier passes
8436 // were darkened by fog already, so we only need to add the fog
8437 // color ontop through the fog mask texture
8439 // if this is an additive blended material, all the earlier passes
8440 // were darkened by fog already, and we should not add fog color
8441 // (because the background was not darkened, there is no fog color
8442 // that was lost behind it).
8443 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]);
8450 rsurfacestate_t rsurface;
8452 void RSurf_ActiveWorldEntity(void)
8454 dp_model_t *model = r_refdef.scene.worldmodel;
8455 //if (rsurface.entity == r_refdef.scene.worldentity)
8457 rsurface.entity = r_refdef.scene.worldentity;
8458 rsurface.skeleton = NULL;
8459 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8460 rsurface.ent_skinnum = 0;
8461 rsurface.ent_qwskin = -1;
8462 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8463 rsurface.shadertime = r_refdef.scene.time;
8464 rsurface.matrix = identitymatrix;
8465 rsurface.inversematrix = identitymatrix;
8466 rsurface.matrixscale = 1;
8467 rsurface.inversematrixscale = 1;
8468 R_EntityMatrix(&identitymatrix);
8469 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8470 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8471 rsurface.fograngerecip = r_refdef.fograngerecip;
8472 rsurface.fogheightfade = r_refdef.fogheightfade;
8473 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8474 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8475 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8476 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8477 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8478 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8479 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8480 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8481 rsurface.colormod[3] = 1;
8482 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);
8483 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8484 rsurface.frameblend[0].lerp = 1;
8485 rsurface.ent_alttextures = false;
8486 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8487 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8488 rsurface.entityskeletaltransform3x4 = NULL;
8489 rsurface.entityskeletaltransform3x4buffer = NULL;
8490 rsurface.entityskeletaltransform3x4offset = 0;
8491 rsurface.entityskeletaltransform3x4size = 0;;
8492 rsurface.entityskeletalnumtransforms = 0;
8493 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8494 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8495 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8496 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8497 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8498 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8499 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8500 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8501 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8502 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8503 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8504 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8505 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8506 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8507 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8508 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8509 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8510 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8511 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8512 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8513 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8514 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8515 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8516 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8517 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8518 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8520 rsurface.modelelement3i = model->surfmesh.data_element3i;
8521 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8522 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8523 rsurface.modelelement3s = model->surfmesh.data_element3s;
8524 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8525 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8526 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8527 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8528 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8529 rsurface.modelsurfaces = model->data_surfaces;
8530 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8531 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8532 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8533 rsurface.modelgeneratedvertex = false;
8534 rsurface.batchgeneratedvertex = false;
8535 rsurface.batchfirstvertex = 0;
8536 rsurface.batchnumvertices = 0;
8537 rsurface.batchfirsttriangle = 0;
8538 rsurface.batchnumtriangles = 0;
8539 rsurface.batchvertex3f = NULL;
8540 rsurface.batchvertex3f_vertexbuffer = NULL;
8541 rsurface.batchvertex3f_bufferoffset = 0;
8542 rsurface.batchsvector3f = NULL;
8543 rsurface.batchsvector3f_vertexbuffer = NULL;
8544 rsurface.batchsvector3f_bufferoffset = 0;
8545 rsurface.batchtvector3f = NULL;
8546 rsurface.batchtvector3f_vertexbuffer = NULL;
8547 rsurface.batchtvector3f_bufferoffset = 0;
8548 rsurface.batchnormal3f = NULL;
8549 rsurface.batchnormal3f_vertexbuffer = NULL;
8550 rsurface.batchnormal3f_bufferoffset = 0;
8551 rsurface.batchlightmapcolor4f = NULL;
8552 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8553 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8554 rsurface.batchtexcoordtexture2f = NULL;
8555 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8556 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8557 rsurface.batchtexcoordlightmap2f = NULL;
8558 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8559 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8560 rsurface.batchskeletalindex4ub = NULL;
8561 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8562 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8563 rsurface.batchskeletalweight4ub = NULL;
8564 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8565 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8566 rsurface.batchvertexmesh = NULL;
8567 rsurface.batchvertexmesh_vertexbuffer = NULL;
8568 rsurface.batchvertexmesh_bufferoffset = 0;
8569 rsurface.batchelement3i = NULL;
8570 rsurface.batchelement3i_indexbuffer = NULL;
8571 rsurface.batchelement3i_bufferoffset = 0;
8572 rsurface.batchelement3s = NULL;
8573 rsurface.batchelement3s_indexbuffer = NULL;
8574 rsurface.batchelement3s_bufferoffset = 0;
8575 rsurface.passcolor4f = NULL;
8576 rsurface.passcolor4f_vertexbuffer = NULL;
8577 rsurface.passcolor4f_bufferoffset = 0;
8578 rsurface.forcecurrenttextureupdate = false;
8581 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8583 dp_model_t *model = ent->model;
8584 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8586 rsurface.entity = (entity_render_t *)ent;
8587 rsurface.skeleton = ent->skeleton;
8588 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8589 rsurface.ent_skinnum = ent->skinnum;
8590 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;
8591 rsurface.ent_flags = ent->flags;
8592 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8593 rsurface.matrix = ent->matrix;
8594 rsurface.inversematrix = ent->inversematrix;
8595 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8596 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8597 R_EntityMatrix(&rsurface.matrix);
8598 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8599 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8600 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8601 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8602 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8603 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8604 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8605 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8606 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8607 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8608 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8609 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8610 rsurface.colormod[3] = ent->alpha;
8611 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8612 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8613 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8614 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8615 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8616 if (ent->model->brush.submodel && !prepass)
8618 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8619 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8621 // if the animcache code decided it should use the shader path, skip the deform step
8622 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8623 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8624 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8625 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8626 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8627 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8629 if (ent->animcache_vertex3f)
8631 r_refdef.stats[r_stat_batch_entitycache_count]++;
8632 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8633 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8634 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8635 rsurface.modelvertex3f = ent->animcache_vertex3f;
8636 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8637 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8638 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8639 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8640 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8641 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8642 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8643 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8644 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8645 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8646 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8647 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8648 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8649 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8651 else if (wanttangents)
8653 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8654 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8655 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8656 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8657 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8658 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8659 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8660 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8661 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8662 rsurface.modelvertexmesh = NULL;
8663 rsurface.modelvertexmesh_vertexbuffer = NULL;
8664 rsurface.modelvertexmesh_bufferoffset = 0;
8665 rsurface.modelvertex3f_vertexbuffer = NULL;
8666 rsurface.modelvertex3f_bufferoffset = 0;
8667 rsurface.modelvertex3f_vertexbuffer = 0;
8668 rsurface.modelvertex3f_bufferoffset = 0;
8669 rsurface.modelsvector3f_vertexbuffer = 0;
8670 rsurface.modelsvector3f_bufferoffset = 0;
8671 rsurface.modeltvector3f_vertexbuffer = 0;
8672 rsurface.modeltvector3f_bufferoffset = 0;
8673 rsurface.modelnormal3f_vertexbuffer = 0;
8674 rsurface.modelnormal3f_bufferoffset = 0;
8676 else if (wantnormals)
8678 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8679 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8680 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8681 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8682 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8683 rsurface.modelsvector3f = NULL;
8684 rsurface.modeltvector3f = NULL;
8685 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8686 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8687 rsurface.modelvertexmesh = NULL;
8688 rsurface.modelvertexmesh_vertexbuffer = NULL;
8689 rsurface.modelvertexmesh_bufferoffset = 0;
8690 rsurface.modelvertex3f_vertexbuffer = NULL;
8691 rsurface.modelvertex3f_bufferoffset = 0;
8692 rsurface.modelvertex3f_vertexbuffer = 0;
8693 rsurface.modelvertex3f_bufferoffset = 0;
8694 rsurface.modelsvector3f_vertexbuffer = 0;
8695 rsurface.modelsvector3f_bufferoffset = 0;
8696 rsurface.modeltvector3f_vertexbuffer = 0;
8697 rsurface.modeltvector3f_bufferoffset = 0;
8698 rsurface.modelnormal3f_vertexbuffer = 0;
8699 rsurface.modelnormal3f_bufferoffset = 0;
8703 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8704 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8705 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8706 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8707 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8708 rsurface.modelsvector3f = NULL;
8709 rsurface.modeltvector3f = NULL;
8710 rsurface.modelnormal3f = NULL;
8711 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8712 rsurface.modelvertexmesh = NULL;
8713 rsurface.modelvertexmesh_vertexbuffer = NULL;
8714 rsurface.modelvertexmesh_bufferoffset = 0;
8715 rsurface.modelvertex3f_vertexbuffer = NULL;
8716 rsurface.modelvertex3f_bufferoffset = 0;
8717 rsurface.modelvertex3f_vertexbuffer = 0;
8718 rsurface.modelvertex3f_bufferoffset = 0;
8719 rsurface.modelsvector3f_vertexbuffer = 0;
8720 rsurface.modelsvector3f_bufferoffset = 0;
8721 rsurface.modeltvector3f_vertexbuffer = 0;
8722 rsurface.modeltvector3f_bufferoffset = 0;
8723 rsurface.modelnormal3f_vertexbuffer = 0;
8724 rsurface.modelnormal3f_bufferoffset = 0;
8726 rsurface.modelgeneratedvertex = true;
8730 if (rsurface.entityskeletaltransform3x4)
8732 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8733 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8734 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8735 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8739 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8740 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8741 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8742 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8744 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8745 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8746 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8747 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8748 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8749 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8750 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8751 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8752 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8753 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8754 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8755 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8756 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8757 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8758 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8759 rsurface.modelgeneratedvertex = false;
8761 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8762 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8763 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8764 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8765 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8766 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8767 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8768 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8769 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8770 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8771 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8772 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8773 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8774 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8775 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8776 rsurface.modelelement3i = model->surfmesh.data_element3i;
8777 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8778 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8779 rsurface.modelelement3s = model->surfmesh.data_element3s;
8780 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8781 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8782 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8783 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8784 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8785 rsurface.modelsurfaces = model->data_surfaces;
8786 rsurface.batchgeneratedvertex = false;
8787 rsurface.batchfirstvertex = 0;
8788 rsurface.batchnumvertices = 0;
8789 rsurface.batchfirsttriangle = 0;
8790 rsurface.batchnumtriangles = 0;
8791 rsurface.batchvertex3f = NULL;
8792 rsurface.batchvertex3f_vertexbuffer = NULL;
8793 rsurface.batchvertex3f_bufferoffset = 0;
8794 rsurface.batchsvector3f = NULL;
8795 rsurface.batchsvector3f_vertexbuffer = NULL;
8796 rsurface.batchsvector3f_bufferoffset = 0;
8797 rsurface.batchtvector3f = NULL;
8798 rsurface.batchtvector3f_vertexbuffer = NULL;
8799 rsurface.batchtvector3f_bufferoffset = 0;
8800 rsurface.batchnormal3f = NULL;
8801 rsurface.batchnormal3f_vertexbuffer = NULL;
8802 rsurface.batchnormal3f_bufferoffset = 0;
8803 rsurface.batchlightmapcolor4f = NULL;
8804 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8805 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8806 rsurface.batchtexcoordtexture2f = NULL;
8807 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8808 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8809 rsurface.batchtexcoordlightmap2f = NULL;
8810 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8811 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8812 rsurface.batchskeletalindex4ub = NULL;
8813 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8814 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8815 rsurface.batchskeletalweight4ub = NULL;
8816 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8817 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8818 rsurface.batchvertexmesh = NULL;
8819 rsurface.batchvertexmesh_vertexbuffer = NULL;
8820 rsurface.batchvertexmesh_bufferoffset = 0;
8821 rsurface.batchelement3i = NULL;
8822 rsurface.batchelement3i_indexbuffer = NULL;
8823 rsurface.batchelement3i_bufferoffset = 0;
8824 rsurface.batchelement3s = NULL;
8825 rsurface.batchelement3s_indexbuffer = NULL;
8826 rsurface.batchelement3s_bufferoffset = 0;
8827 rsurface.passcolor4f = NULL;
8828 rsurface.passcolor4f_vertexbuffer = NULL;
8829 rsurface.passcolor4f_bufferoffset = 0;
8830 rsurface.forcecurrenttextureupdate = false;
8833 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)
8835 rsurface.entity = r_refdef.scene.worldentity;
8836 rsurface.skeleton = NULL;
8837 rsurface.ent_skinnum = 0;
8838 rsurface.ent_qwskin = -1;
8839 rsurface.ent_flags = entflags;
8840 rsurface.shadertime = r_refdef.scene.time - shadertime;
8841 rsurface.modelnumvertices = numvertices;
8842 rsurface.modelnumtriangles = numtriangles;
8843 rsurface.matrix = *matrix;
8844 rsurface.inversematrix = *inversematrix;
8845 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8846 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8847 R_EntityMatrix(&rsurface.matrix);
8848 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8849 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8850 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8851 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8852 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8853 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8854 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8855 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8856 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8857 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8858 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8859 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8860 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);
8861 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8862 rsurface.frameblend[0].lerp = 1;
8863 rsurface.ent_alttextures = false;
8864 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8865 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8866 rsurface.entityskeletaltransform3x4 = NULL;
8867 rsurface.entityskeletaltransform3x4buffer = NULL;
8868 rsurface.entityskeletaltransform3x4offset = 0;
8869 rsurface.entityskeletaltransform3x4size = 0;
8870 rsurface.entityskeletalnumtransforms = 0;
8871 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8872 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8873 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8874 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8877 rsurface.modelvertex3f = (float *)vertex3f;
8878 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8879 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8880 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8882 else if (wantnormals)
8884 rsurface.modelvertex3f = (float *)vertex3f;
8885 rsurface.modelsvector3f = NULL;
8886 rsurface.modeltvector3f = NULL;
8887 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8891 rsurface.modelvertex3f = (float *)vertex3f;
8892 rsurface.modelsvector3f = NULL;
8893 rsurface.modeltvector3f = NULL;
8894 rsurface.modelnormal3f = NULL;
8896 rsurface.modelvertexmesh = NULL;
8897 rsurface.modelvertexmesh_vertexbuffer = NULL;
8898 rsurface.modelvertexmesh_bufferoffset = 0;
8899 rsurface.modelvertex3f_vertexbuffer = 0;
8900 rsurface.modelvertex3f_bufferoffset = 0;
8901 rsurface.modelsvector3f_vertexbuffer = 0;
8902 rsurface.modelsvector3f_bufferoffset = 0;
8903 rsurface.modeltvector3f_vertexbuffer = 0;
8904 rsurface.modeltvector3f_bufferoffset = 0;
8905 rsurface.modelnormal3f_vertexbuffer = 0;
8906 rsurface.modelnormal3f_bufferoffset = 0;
8907 rsurface.modelgeneratedvertex = true;
8908 rsurface.modellightmapcolor4f = (float *)color4f;
8909 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8910 rsurface.modellightmapcolor4f_bufferoffset = 0;
8911 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8912 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8913 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8914 rsurface.modeltexcoordlightmap2f = NULL;
8915 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8916 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8917 rsurface.modelskeletalindex4ub = NULL;
8918 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8919 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8920 rsurface.modelskeletalweight4ub = NULL;
8921 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8922 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8923 rsurface.modelelement3i = (int *)element3i;
8924 rsurface.modelelement3i_indexbuffer = NULL;
8925 rsurface.modelelement3i_bufferoffset = 0;
8926 rsurface.modelelement3s = (unsigned short *)element3s;
8927 rsurface.modelelement3s_indexbuffer = NULL;
8928 rsurface.modelelement3s_bufferoffset = 0;
8929 rsurface.modellightmapoffsets = NULL;
8930 rsurface.modelsurfaces = NULL;
8931 rsurface.batchgeneratedvertex = false;
8932 rsurface.batchfirstvertex = 0;
8933 rsurface.batchnumvertices = 0;
8934 rsurface.batchfirsttriangle = 0;
8935 rsurface.batchnumtriangles = 0;
8936 rsurface.batchvertex3f = NULL;
8937 rsurface.batchvertex3f_vertexbuffer = NULL;
8938 rsurface.batchvertex3f_bufferoffset = 0;
8939 rsurface.batchsvector3f = NULL;
8940 rsurface.batchsvector3f_vertexbuffer = NULL;
8941 rsurface.batchsvector3f_bufferoffset = 0;
8942 rsurface.batchtvector3f = NULL;
8943 rsurface.batchtvector3f_vertexbuffer = NULL;
8944 rsurface.batchtvector3f_bufferoffset = 0;
8945 rsurface.batchnormal3f = NULL;
8946 rsurface.batchnormal3f_vertexbuffer = NULL;
8947 rsurface.batchnormal3f_bufferoffset = 0;
8948 rsurface.batchlightmapcolor4f = NULL;
8949 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8950 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8951 rsurface.batchtexcoordtexture2f = NULL;
8952 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8953 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8954 rsurface.batchtexcoordlightmap2f = NULL;
8955 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8956 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8957 rsurface.batchskeletalindex4ub = NULL;
8958 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8959 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8960 rsurface.batchskeletalweight4ub = NULL;
8961 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8962 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8963 rsurface.batchvertexmesh = NULL;
8964 rsurface.batchvertexmesh_vertexbuffer = NULL;
8965 rsurface.batchvertexmesh_bufferoffset = 0;
8966 rsurface.batchelement3i = NULL;
8967 rsurface.batchelement3i_indexbuffer = NULL;
8968 rsurface.batchelement3i_bufferoffset = 0;
8969 rsurface.batchelement3s = NULL;
8970 rsurface.batchelement3s_indexbuffer = NULL;
8971 rsurface.batchelement3s_bufferoffset = 0;
8972 rsurface.passcolor4f = NULL;
8973 rsurface.passcolor4f_vertexbuffer = NULL;
8974 rsurface.passcolor4f_bufferoffset = 0;
8975 rsurface.forcecurrenttextureupdate = true;
8977 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8979 if ((wantnormals || wanttangents) && !normal3f)
8981 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8982 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8984 if (wanttangents && !svector3f)
8986 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8987 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8988 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8993 float RSurf_FogPoint(const float *v)
8995 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8996 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8997 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8998 float FogHeightFade = r_refdef.fogheightfade;
9000 unsigned int fogmasktableindex;
9001 if (r_refdef.fogplaneviewabove)
9002 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9004 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9005 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9006 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9009 float RSurf_FogVertex(const float *v)
9011 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9012 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9013 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9014 float FogHeightFade = rsurface.fogheightfade;
9016 unsigned int fogmasktableindex;
9017 if (r_refdef.fogplaneviewabove)
9018 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9020 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9021 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9022 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9025 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9028 for (i = 0;i < numelements;i++)
9029 outelement3i[i] = inelement3i[i] + adjust;
9032 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9033 extern cvar_t gl_vbo;
9034 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9042 int surfacefirsttriangle;
9043 int surfacenumtriangles;
9044 int surfacefirstvertex;
9045 int surfaceendvertex;
9046 int surfacenumvertices;
9047 int batchnumsurfaces = texturenumsurfaces;
9048 int batchnumvertices;
9049 int batchnumtriangles;
9053 qboolean dynamicvertex;
9057 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9060 q3shaderinfo_deform_t *deform;
9061 const msurface_t *surface, *firstsurface;
9062 r_vertexmesh_t *vertexmesh;
9063 if (!texturenumsurfaces)
9065 // find vertex range of this surface batch
9067 firstsurface = texturesurfacelist[0];
9068 firsttriangle = firstsurface->num_firsttriangle;
9069 batchnumvertices = 0;
9070 batchnumtriangles = 0;
9071 firstvertex = endvertex = firstsurface->num_firstvertex;
9072 for (i = 0;i < texturenumsurfaces;i++)
9074 surface = texturesurfacelist[i];
9075 if (surface != firstsurface + i)
9077 surfacefirstvertex = surface->num_firstvertex;
9078 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9079 surfacenumvertices = surface->num_vertices;
9080 surfacenumtriangles = surface->num_triangles;
9081 if (firstvertex > surfacefirstvertex)
9082 firstvertex = surfacefirstvertex;
9083 if (endvertex < surfaceendvertex)
9084 endvertex = surfaceendvertex;
9085 batchnumvertices += surfacenumvertices;
9086 batchnumtriangles += surfacenumtriangles;
9089 r_refdef.stats[r_stat_batch_batches]++;
9091 r_refdef.stats[r_stat_batch_withgaps]++;
9092 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9093 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9094 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9096 // we now know the vertex range used, and if there are any gaps in it
9097 rsurface.batchfirstvertex = firstvertex;
9098 rsurface.batchnumvertices = endvertex - firstvertex;
9099 rsurface.batchfirsttriangle = firsttriangle;
9100 rsurface.batchnumtriangles = batchnumtriangles;
9102 // this variable holds flags for which properties have been updated that
9103 // may require regenerating vertexmesh array...
9106 // check if any dynamic vertex processing must occur
9107 dynamicvertex = false;
9109 // a cvar to force the dynamic vertex path to be taken, for debugging
9110 if (r_batch_debugdynamicvertexpath.integer)
9114 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9115 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9116 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9117 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9119 dynamicvertex = true;
9122 // if there is a chance of animated vertex colors, it's a dynamic batch
9123 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9127 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9128 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9129 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9130 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9132 dynamicvertex = true;
9133 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9136 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9138 switch (deform->deform)
9141 case Q3DEFORM_PROJECTIONSHADOW:
9142 case Q3DEFORM_TEXT0:
9143 case Q3DEFORM_TEXT1:
9144 case Q3DEFORM_TEXT2:
9145 case Q3DEFORM_TEXT3:
9146 case Q3DEFORM_TEXT4:
9147 case Q3DEFORM_TEXT5:
9148 case Q3DEFORM_TEXT6:
9149 case Q3DEFORM_TEXT7:
9152 case Q3DEFORM_AUTOSPRITE:
9155 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9156 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9157 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9158 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9160 dynamicvertex = true;
9161 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9162 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9164 case Q3DEFORM_AUTOSPRITE2:
9167 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9168 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9169 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9170 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9172 dynamicvertex = true;
9173 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9174 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9176 case Q3DEFORM_NORMAL:
9179 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9180 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9181 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9182 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9184 dynamicvertex = true;
9185 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9186 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9189 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9190 break; // if wavefunc is a nop, ignore this transform
9193 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9194 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9195 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9196 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9198 dynamicvertex = true;
9199 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9200 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9202 case Q3DEFORM_BULGE:
9205 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9206 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9207 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9208 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9210 dynamicvertex = true;
9211 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9212 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9215 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9216 break; // if wavefunc is a nop, ignore this transform
9219 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9220 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9221 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9222 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9224 dynamicvertex = true;
9225 batchneed |= BATCHNEED_ARRAY_VERTEX;
9226 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9230 switch(rsurface.texture->tcgen.tcgen)
9233 case Q3TCGEN_TEXTURE:
9235 case Q3TCGEN_LIGHTMAP:
9238 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9239 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9240 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9241 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9243 dynamicvertex = true;
9244 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9245 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9247 case Q3TCGEN_VECTOR:
9250 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9251 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9252 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9253 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9255 dynamicvertex = true;
9256 batchneed |= BATCHNEED_ARRAY_VERTEX;
9257 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9259 case Q3TCGEN_ENVIRONMENT:
9262 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9263 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9264 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9265 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9267 dynamicvertex = true;
9268 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9269 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9272 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9276 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9277 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9278 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9279 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9281 dynamicvertex = true;
9282 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9283 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9286 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9290 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9291 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9292 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9293 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9295 dynamicvertex = true;
9296 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9299 // when the model data has no vertex buffer (dynamic mesh), we need to
9301 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9302 batchneed |= BATCHNEED_NOGAPS;
9304 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9305 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9306 // we ensure this by treating the vertex batch as dynamic...
9307 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9311 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9312 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9313 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9314 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9316 dynamicvertex = true;
9321 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9322 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9323 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9324 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9325 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9326 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9327 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9328 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9331 // if needsupdate, we have to do a dynamic vertex batch for sure
9332 if (needsupdate & batchneed)
9336 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9337 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9338 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9339 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9341 dynamicvertex = true;
9344 // see if we need to build vertexmesh from arrays
9345 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9349 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9350 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9351 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9352 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9354 dynamicvertex = true;
9357 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9358 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9359 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9361 rsurface.batchvertex3f = rsurface.modelvertex3f;
9362 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9363 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9364 rsurface.batchsvector3f = rsurface.modelsvector3f;
9365 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9366 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9367 rsurface.batchtvector3f = rsurface.modeltvector3f;
9368 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9369 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9370 rsurface.batchnormal3f = rsurface.modelnormal3f;
9371 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9372 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9373 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9374 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9375 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9376 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9377 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9378 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9379 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9380 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9381 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9382 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9383 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9384 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9385 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9386 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9387 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9388 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9389 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9390 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9391 rsurface.batchelement3i = rsurface.modelelement3i;
9392 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9393 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9394 rsurface.batchelement3s = rsurface.modelelement3s;
9395 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9396 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9397 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9398 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9399 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9400 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9401 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9403 // if any dynamic vertex processing has to occur in software, we copy the
9404 // entire surface list together before processing to rebase the vertices
9405 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9407 // if any gaps exist and we do not have a static vertex buffer, we have to
9408 // copy the surface list together to avoid wasting upload bandwidth on the
9409 // vertices in the gaps.
9411 // if gaps exist and we have a static vertex buffer, we can choose whether
9412 // to combine the index buffer ranges into one dynamic index buffer or
9413 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9415 // in many cases the batch is reduced to one draw call.
9417 rsurface.batchmultidraw = false;
9418 rsurface.batchmultidrawnumsurfaces = 0;
9419 rsurface.batchmultidrawsurfacelist = NULL;
9423 // static vertex data, just set pointers...
9424 rsurface.batchgeneratedvertex = false;
9425 // if there are gaps, we want to build a combined index buffer,
9426 // otherwise use the original static buffer with an appropriate offset
9429 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9430 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9431 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9432 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9433 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9435 rsurface.batchmultidraw = true;
9436 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9437 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9440 // build a new triangle elements array for this batch
9441 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9442 rsurface.batchfirsttriangle = 0;
9444 for (i = 0;i < texturenumsurfaces;i++)
9446 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9447 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9448 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9449 numtriangles += surfacenumtriangles;
9451 rsurface.batchelement3i_indexbuffer = NULL;
9452 rsurface.batchelement3i_bufferoffset = 0;
9453 rsurface.batchelement3s = NULL;
9454 rsurface.batchelement3s_indexbuffer = NULL;
9455 rsurface.batchelement3s_bufferoffset = 0;
9456 if (endvertex <= 65536)
9458 // make a 16bit (unsigned short) index array if possible
9459 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9460 for (i = 0;i < numtriangles*3;i++)
9461 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9463 // upload buffer data for the copytriangles batch
9464 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9466 if (rsurface.batchelement3s)
9467 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9468 else if (rsurface.batchelement3i)
9469 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9474 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9475 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9476 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9477 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9482 // something needs software processing, do it for real...
9483 // we only directly handle separate array data in this case and then
9484 // generate interleaved data if needed...
9485 rsurface.batchgeneratedvertex = true;
9486 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9487 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9488 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9489 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9491 // now copy the vertex data into a combined array and make an index array
9492 // (this is what Quake3 does all the time)
9493 // we also apply any skeletal animation here that would have been done in
9494 // the vertex shader, because most of the dynamic vertex animation cases
9495 // need actual vertex positions and normals
9496 //if (dynamicvertex)
9498 rsurface.batchvertexmesh = NULL;
9499 rsurface.batchvertexmesh_vertexbuffer = NULL;
9500 rsurface.batchvertexmesh_bufferoffset = 0;
9501 rsurface.batchvertex3f = NULL;
9502 rsurface.batchvertex3f_vertexbuffer = NULL;
9503 rsurface.batchvertex3f_bufferoffset = 0;
9504 rsurface.batchsvector3f = NULL;
9505 rsurface.batchsvector3f_vertexbuffer = NULL;
9506 rsurface.batchsvector3f_bufferoffset = 0;
9507 rsurface.batchtvector3f = NULL;
9508 rsurface.batchtvector3f_vertexbuffer = NULL;
9509 rsurface.batchtvector3f_bufferoffset = 0;
9510 rsurface.batchnormal3f = NULL;
9511 rsurface.batchnormal3f_vertexbuffer = NULL;
9512 rsurface.batchnormal3f_bufferoffset = 0;
9513 rsurface.batchlightmapcolor4f = NULL;
9514 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9515 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9516 rsurface.batchtexcoordtexture2f = NULL;
9517 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9518 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9519 rsurface.batchtexcoordlightmap2f = NULL;
9520 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9521 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9522 rsurface.batchskeletalindex4ub = NULL;
9523 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9524 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9525 rsurface.batchskeletalweight4ub = NULL;
9526 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9527 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9528 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9529 rsurface.batchelement3i_indexbuffer = NULL;
9530 rsurface.batchelement3i_bufferoffset = 0;
9531 rsurface.batchelement3s = NULL;
9532 rsurface.batchelement3s_indexbuffer = NULL;
9533 rsurface.batchelement3s_bufferoffset = 0;
9534 rsurface.batchskeletaltransform3x4buffer = NULL;
9535 rsurface.batchskeletaltransform3x4offset = 0;
9536 rsurface.batchskeletaltransform3x4size = 0;
9537 // we'll only be setting up certain arrays as needed
9538 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9539 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9540 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9541 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9542 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9543 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9544 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9546 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9547 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9549 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9550 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9551 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9552 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9553 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9554 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9555 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9557 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9558 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9562 for (i = 0;i < texturenumsurfaces;i++)
9564 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9565 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9566 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9567 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9568 // copy only the data requested
9569 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9570 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9571 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9573 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9575 if (rsurface.batchvertex3f)
9576 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9578 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9580 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9582 if (rsurface.modelnormal3f)
9583 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9585 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9587 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9589 if (rsurface.modelsvector3f)
9591 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9592 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9596 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9597 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9600 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9602 if (rsurface.modellightmapcolor4f)
9603 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9605 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9607 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9609 if (rsurface.modeltexcoordtexture2f)
9610 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9612 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9614 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9616 if (rsurface.modeltexcoordlightmap2f)
9617 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9619 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9621 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9623 if (rsurface.modelskeletalindex4ub)
9625 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9626 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9630 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9631 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9632 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9633 for (j = 0;j < surfacenumvertices;j++)
9638 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9639 numvertices += surfacenumvertices;
9640 numtriangles += surfacenumtriangles;
9643 // generate a 16bit index array as well if possible
9644 // (in general, dynamic batches fit)
9645 if (numvertices <= 65536)
9647 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9648 for (i = 0;i < numtriangles*3;i++)
9649 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9652 // since we've copied everything, the batch now starts at 0
9653 rsurface.batchfirstvertex = 0;
9654 rsurface.batchnumvertices = batchnumvertices;
9655 rsurface.batchfirsttriangle = 0;
9656 rsurface.batchnumtriangles = batchnumtriangles;
9659 // apply skeletal animation that would have been done in the vertex shader
9660 if (rsurface.batchskeletaltransform3x4)
9662 const unsigned char *si;
9663 const unsigned char *sw;
9665 const float *b = rsurface.batchskeletaltransform3x4;
9666 float *vp, *vs, *vt, *vn;
9668 float m[3][4], n[3][4];
9669 float tp[3], ts[3], tt[3], tn[3];
9670 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9671 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9672 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9673 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9674 si = rsurface.batchskeletalindex4ub;
9675 sw = rsurface.batchskeletalweight4ub;
9676 vp = rsurface.batchvertex3f;
9677 vs = rsurface.batchsvector3f;
9678 vt = rsurface.batchtvector3f;
9679 vn = rsurface.batchnormal3f;
9680 memset(m[0], 0, sizeof(m));
9681 memset(n[0], 0, sizeof(n));
9682 for (i = 0;i < batchnumvertices;i++)
9684 t[0] = b + si[0]*12;
9687 // common case - only one matrix
9701 else if (sw[2] + sw[3])
9704 t[1] = b + si[1]*12;
9705 t[2] = b + si[2]*12;
9706 t[3] = b + si[3]*12;
9707 w[0] = sw[0] * (1.0f / 255.0f);
9708 w[1] = sw[1] * (1.0f / 255.0f);
9709 w[2] = sw[2] * (1.0f / 255.0f);
9710 w[3] = sw[3] * (1.0f / 255.0f);
9711 // blend the matrices
9712 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9713 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9714 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9715 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9716 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9717 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9718 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9719 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9720 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9721 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9722 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9723 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9728 t[1] = b + si[1]*12;
9729 w[0] = sw[0] * (1.0f / 255.0f);
9730 w[1] = sw[1] * (1.0f / 255.0f);
9731 // blend the matrices
9732 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9733 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9734 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9735 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9736 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9737 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9738 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9739 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9740 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9741 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9742 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9743 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9747 // modify the vertex
9749 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9750 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9751 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9755 // the normal transformation matrix is a set of cross products...
9756 CrossProduct(m[1], m[2], n[0]);
9757 CrossProduct(m[2], m[0], n[1]);
9758 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9760 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9761 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9762 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9763 VectorNormalize(vn);
9768 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9769 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9770 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9771 VectorNormalize(vs);
9774 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9775 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9776 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9777 VectorNormalize(vt);
9782 rsurface.batchskeletaltransform3x4 = NULL;
9783 rsurface.batchskeletalnumtransforms = 0;
9786 // q1bsp surfaces rendered in vertex color mode have to have colors
9787 // calculated based on lightstyles
9788 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9790 // generate color arrays for the surfaces in this list
9795 const unsigned char *lm;
9796 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9797 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9798 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9800 for (i = 0;i < texturenumsurfaces;i++)
9802 surface = texturesurfacelist[i];
9803 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9804 surfacenumvertices = surface->num_vertices;
9805 if (surface->lightmapinfo->samples)
9807 for (j = 0;j < surfacenumvertices;j++)
9809 lm = surface->lightmapinfo->samples + offsets[j];
9810 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9811 VectorScale(lm, scale, c);
9812 if (surface->lightmapinfo->styles[1] != 255)
9814 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9816 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9817 VectorMA(c, scale, lm, c);
9818 if (surface->lightmapinfo->styles[2] != 255)
9821 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9822 VectorMA(c, scale, lm, c);
9823 if (surface->lightmapinfo->styles[3] != 255)
9826 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9827 VectorMA(c, scale, lm, c);
9834 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);
9840 for (j = 0;j < surfacenumvertices;j++)
9842 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9849 // if vertices are deformed (sprite flares and things in maps, possibly
9850 // water waves, bulges and other deformations), modify the copied vertices
9852 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9854 switch (deform->deform)
9857 case Q3DEFORM_PROJECTIONSHADOW:
9858 case Q3DEFORM_TEXT0:
9859 case Q3DEFORM_TEXT1:
9860 case Q3DEFORM_TEXT2:
9861 case Q3DEFORM_TEXT3:
9862 case Q3DEFORM_TEXT4:
9863 case Q3DEFORM_TEXT5:
9864 case Q3DEFORM_TEXT6:
9865 case Q3DEFORM_TEXT7:
9868 case Q3DEFORM_AUTOSPRITE:
9869 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9870 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9871 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9872 VectorNormalize(newforward);
9873 VectorNormalize(newright);
9874 VectorNormalize(newup);
9875 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9876 // rsurface.batchvertex3f_vertexbuffer = NULL;
9877 // rsurface.batchvertex3f_bufferoffset = 0;
9878 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9879 // rsurface.batchsvector3f_vertexbuffer = NULL;
9880 // rsurface.batchsvector3f_bufferoffset = 0;
9881 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9882 // rsurface.batchtvector3f_vertexbuffer = NULL;
9883 // rsurface.batchtvector3f_bufferoffset = 0;
9884 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9885 // rsurface.batchnormal3f_vertexbuffer = NULL;
9886 // rsurface.batchnormal3f_bufferoffset = 0;
9887 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9888 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9889 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9890 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9891 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);
9892 // a single autosprite surface can contain multiple sprites...
9893 for (j = 0;j < batchnumvertices - 3;j += 4)
9895 VectorClear(center);
9896 for (i = 0;i < 4;i++)
9897 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9898 VectorScale(center, 0.25f, center);
9899 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9900 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9901 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9902 for (i = 0;i < 4;i++)
9904 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9905 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9908 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9909 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9910 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);
9912 case Q3DEFORM_AUTOSPRITE2:
9913 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9914 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9915 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9916 VectorNormalize(newforward);
9917 VectorNormalize(newright);
9918 VectorNormalize(newup);
9919 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9920 // rsurface.batchvertex3f_vertexbuffer = NULL;
9921 // rsurface.batchvertex3f_bufferoffset = 0;
9923 const float *v1, *v2;
9933 memset(shortest, 0, sizeof(shortest));
9934 // a single autosprite surface can contain multiple sprites...
9935 for (j = 0;j < batchnumvertices - 3;j += 4)
9937 VectorClear(center);
9938 for (i = 0;i < 4;i++)
9939 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9940 VectorScale(center, 0.25f, center);
9941 // find the two shortest edges, then use them to define the
9942 // axis vectors for rotating around the central axis
9943 for (i = 0;i < 6;i++)
9945 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9946 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9947 l = VectorDistance2(v1, v2);
9948 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9950 l += (1.0f / 1024.0f);
9951 if (shortest[0].length2 > l || i == 0)
9953 shortest[1] = shortest[0];
9954 shortest[0].length2 = l;
9955 shortest[0].v1 = v1;
9956 shortest[0].v2 = v2;
9958 else if (shortest[1].length2 > l || i == 1)
9960 shortest[1].length2 = l;
9961 shortest[1].v1 = v1;
9962 shortest[1].v2 = v2;
9965 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9966 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9967 // this calculates the right vector from the shortest edge
9968 // and the up vector from the edge midpoints
9969 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9970 VectorNormalize(right);
9971 VectorSubtract(end, start, up);
9972 VectorNormalize(up);
9973 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9974 VectorSubtract(rsurface.localvieworigin, center, forward);
9975 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9976 VectorNegate(forward, forward);
9977 VectorReflect(forward, 0, up, forward);
9978 VectorNormalize(forward);
9979 CrossProduct(up, forward, newright);
9980 VectorNormalize(newright);
9981 // rotate the quad around the up axis vector, this is made
9982 // especially easy by the fact we know the quad is flat,
9983 // so we only have to subtract the center position and
9984 // measure distance along the right vector, and then
9985 // multiply that by the newright vector and add back the
9987 // we also need to subtract the old position to undo the
9988 // displacement from the center, which we do with a
9989 // DotProduct, the subtraction/addition of center is also
9990 // optimized into DotProducts here
9991 l = DotProduct(right, center);
9992 for (i = 0;i < 4;i++)
9994 v1 = rsurface.batchvertex3f + 3*(j+i);
9995 f = DotProduct(right, v1) - l;
9996 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10000 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10002 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10003 // rsurface.batchnormal3f_vertexbuffer = NULL;
10004 // rsurface.batchnormal3f_bufferoffset = 0;
10005 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10007 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10009 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10010 // rsurface.batchsvector3f_vertexbuffer = NULL;
10011 // rsurface.batchsvector3f_bufferoffset = 0;
10012 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10013 // rsurface.batchtvector3f_vertexbuffer = NULL;
10014 // rsurface.batchtvector3f_bufferoffset = 0;
10015 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);
10018 case Q3DEFORM_NORMAL:
10019 // deform the normals to make reflections wavey
10020 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10021 rsurface.batchnormal3f_vertexbuffer = NULL;
10022 rsurface.batchnormal3f_bufferoffset = 0;
10023 for (j = 0;j < batchnumvertices;j++)
10026 float *normal = rsurface.batchnormal3f + 3*j;
10027 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10028 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10029 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10030 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10031 VectorNormalize(normal);
10033 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10035 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10036 // rsurface.batchsvector3f_vertexbuffer = NULL;
10037 // rsurface.batchsvector3f_bufferoffset = 0;
10038 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10039 // rsurface.batchtvector3f_vertexbuffer = NULL;
10040 // rsurface.batchtvector3f_bufferoffset = 0;
10041 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);
10044 case Q3DEFORM_WAVE:
10045 // deform vertex array to make wavey water and flags and such
10046 waveparms[0] = deform->waveparms[0];
10047 waveparms[1] = deform->waveparms[1];
10048 waveparms[2] = deform->waveparms[2];
10049 waveparms[3] = deform->waveparms[3];
10050 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10051 break; // if wavefunc is a nop, don't make a dynamic vertex array
10052 // this is how a divisor of vertex influence on deformation
10053 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10054 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10055 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10056 // rsurface.batchvertex3f_vertexbuffer = NULL;
10057 // rsurface.batchvertex3f_bufferoffset = 0;
10058 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10059 // rsurface.batchnormal3f_vertexbuffer = NULL;
10060 // rsurface.batchnormal3f_bufferoffset = 0;
10061 for (j = 0;j < batchnumvertices;j++)
10063 // if the wavefunc depends on time, evaluate it per-vertex
10066 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10067 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10069 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10071 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10072 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10073 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10075 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10076 // rsurface.batchsvector3f_vertexbuffer = NULL;
10077 // rsurface.batchsvector3f_bufferoffset = 0;
10078 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10079 // rsurface.batchtvector3f_vertexbuffer = NULL;
10080 // rsurface.batchtvector3f_bufferoffset = 0;
10081 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);
10084 case Q3DEFORM_BULGE:
10085 // deform vertex array to make the surface have moving bulges
10086 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10087 // rsurface.batchvertex3f_vertexbuffer = NULL;
10088 // rsurface.batchvertex3f_bufferoffset = 0;
10089 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10090 // rsurface.batchnormal3f_vertexbuffer = NULL;
10091 // rsurface.batchnormal3f_bufferoffset = 0;
10092 for (j = 0;j < batchnumvertices;j++)
10094 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10095 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10097 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10098 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10099 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10101 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10102 // rsurface.batchsvector3f_vertexbuffer = NULL;
10103 // rsurface.batchsvector3f_bufferoffset = 0;
10104 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10105 // rsurface.batchtvector3f_vertexbuffer = NULL;
10106 // rsurface.batchtvector3f_bufferoffset = 0;
10107 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);
10110 case Q3DEFORM_MOVE:
10111 // deform vertex array
10112 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10113 break; // if wavefunc is a nop, don't make a dynamic vertex array
10114 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10115 VectorScale(deform->parms, scale, waveparms);
10116 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10117 // rsurface.batchvertex3f_vertexbuffer = NULL;
10118 // rsurface.batchvertex3f_bufferoffset = 0;
10119 for (j = 0;j < batchnumvertices;j++)
10120 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10125 if (rsurface.batchtexcoordtexture2f)
10127 // generate texcoords based on the chosen texcoord source
10128 switch(rsurface.texture->tcgen.tcgen)
10131 case Q3TCGEN_TEXTURE:
10133 case Q3TCGEN_LIGHTMAP:
10134 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10135 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10136 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10137 if (rsurface.batchtexcoordlightmap2f)
10138 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10140 case Q3TCGEN_VECTOR:
10141 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10142 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10143 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10144 for (j = 0;j < batchnumvertices;j++)
10146 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10147 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10150 case Q3TCGEN_ENVIRONMENT:
10151 // make environment reflections using a spheremap
10152 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10153 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10154 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10155 for (j = 0;j < batchnumvertices;j++)
10157 // identical to Q3A's method, but executed in worldspace so
10158 // carried models can be shiny too
10160 float viewer[3], d, reflected[3], worldreflected[3];
10162 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10163 // VectorNormalize(viewer);
10165 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10167 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10168 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10169 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10170 // note: this is proportinal to viewer, so we can normalize later
10172 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10173 VectorNormalize(worldreflected);
10175 // note: this sphere map only uses world x and z!
10176 // so positive and negative y will LOOK THE SAME.
10177 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10178 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10182 // the only tcmod that needs software vertex processing is turbulent, so
10183 // check for it here and apply the changes if needed
10184 // and we only support that as the first one
10185 // (handling a mixture of turbulent and other tcmods would be problematic
10186 // without punting it entirely to a software path)
10187 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10189 amplitude = rsurface.texture->tcmods[0].parms[1];
10190 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10191 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10192 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10193 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10194 for (j = 0;j < batchnumvertices;j++)
10196 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);
10197 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10202 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10204 // convert the modified arrays to vertex structs
10205 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10206 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10207 // rsurface.batchvertexmesh_bufferoffset = 0;
10208 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10209 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10210 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10211 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10212 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10213 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10214 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10216 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10218 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10219 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10222 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10223 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10224 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10225 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10226 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10227 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10228 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10229 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10230 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10231 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10233 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10235 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10236 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10241 // upload buffer data for the dynamic batch
10242 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10244 if (rsurface.batchvertexmesh)
10245 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10248 if (rsurface.batchvertex3f)
10249 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10250 if (rsurface.batchsvector3f)
10251 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10252 if (rsurface.batchtvector3f)
10253 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10254 if (rsurface.batchnormal3f)
10255 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10256 if (rsurface.batchlightmapcolor4f)
10257 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10258 if (rsurface.batchtexcoordtexture2f)
10259 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10260 if (rsurface.batchtexcoordlightmap2f)
10261 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10262 if (rsurface.batchskeletalindex4ub)
10263 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10264 if (rsurface.batchskeletalweight4ub)
10265 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10267 if (rsurface.batchelement3s)
10268 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10269 else if (rsurface.batchelement3i)
10270 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10274 void RSurf_DrawBatch(void)
10276 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10277 // through the pipeline, killing it earlier in the pipeline would have
10278 // per-surface overhead rather than per-batch overhead, so it's best to
10279 // reject it here, before it hits glDraw.
10280 if (rsurface.batchnumtriangles == 0)
10283 // batch debugging code
10284 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10290 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10291 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10294 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10296 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10298 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10299 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);
10306 if (rsurface.batchmultidraw)
10308 // issue multiple draws rather than copying index data
10309 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10310 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10311 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10312 for (i = 0;i < numsurfaces;)
10314 // combine consecutive surfaces as one draw
10315 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10316 if (surfacelist[j] != surfacelist[k] + 1)
10318 firstvertex = surfacelist[i]->num_firstvertex;
10319 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10320 firsttriangle = surfacelist[i]->num_firsttriangle;
10321 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10322 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);
10328 // there is only one consecutive run of index data (may have been combined)
10329 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);
10333 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10335 // pick the closest matching water plane
10336 int planeindex, vertexindex, bestplaneindex = -1;
10340 r_waterstate_waterplane_t *p;
10341 qboolean prepared = false;
10343 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10345 if(p->camera_entity != rsurface.texture->camera_entity)
10350 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10352 if(rsurface.batchnumvertices == 0)
10355 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10357 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10358 d += fabs(PlaneDiff(vert, &p->plane));
10360 if (bestd > d || bestplaneindex < 0)
10363 bestplaneindex = planeindex;
10366 return bestplaneindex;
10367 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10368 // this situation though, as it might be better to render single larger
10369 // batches with useless stuff (backface culled for example) than to
10370 // render multiple smaller batches
10373 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10376 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10377 rsurface.passcolor4f_vertexbuffer = 0;
10378 rsurface.passcolor4f_bufferoffset = 0;
10379 for (i = 0;i < rsurface.batchnumvertices;i++)
10380 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10383 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10390 if (rsurface.passcolor4f)
10392 // generate color arrays
10393 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10394 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10395 rsurface.passcolor4f_vertexbuffer = 0;
10396 rsurface.passcolor4f_bufferoffset = 0;
10397 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)
10399 f = RSurf_FogVertex(v);
10408 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10409 rsurface.passcolor4f_vertexbuffer = 0;
10410 rsurface.passcolor4f_bufferoffset = 0;
10411 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10413 f = RSurf_FogVertex(v);
10422 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10429 if (!rsurface.passcolor4f)
10431 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10432 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10433 rsurface.passcolor4f_vertexbuffer = 0;
10434 rsurface.passcolor4f_bufferoffset = 0;
10435 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)
10437 f = RSurf_FogVertex(v);
10438 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10439 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10440 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10445 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10450 if (!rsurface.passcolor4f)
10452 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10453 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10454 rsurface.passcolor4f_vertexbuffer = 0;
10455 rsurface.passcolor4f_bufferoffset = 0;
10456 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10465 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10470 if (!rsurface.passcolor4f)
10472 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10473 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10474 rsurface.passcolor4f_vertexbuffer = 0;
10475 rsurface.passcolor4f_bufferoffset = 0;
10476 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10478 c2[0] = c[0] + r_refdef.scene.ambient;
10479 c2[1] = c[1] + r_refdef.scene.ambient;
10480 c2[2] = c[2] + r_refdef.scene.ambient;
10485 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10488 rsurface.passcolor4f = NULL;
10489 rsurface.passcolor4f_vertexbuffer = 0;
10490 rsurface.passcolor4f_bufferoffset = 0;
10491 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10492 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10493 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10494 GL_Color(r, g, b, a);
10495 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10496 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10497 R_Mesh_TexMatrix(0, NULL);
10501 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10503 // TODO: optimize applyfog && applycolor case
10504 // just apply fog if necessary, and tint the fog color array if necessary
10505 rsurface.passcolor4f = NULL;
10506 rsurface.passcolor4f_vertexbuffer = 0;
10507 rsurface.passcolor4f_bufferoffset = 0;
10508 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10509 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10510 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10511 GL_Color(r, g, b, a);
10515 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10518 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10519 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10520 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10521 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10522 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10523 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10524 GL_Color(r, g, b, a);
10528 static void RSurf_DrawBatch_GL11_ClampColor(void)
10533 if (!rsurface.passcolor4f)
10535 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10537 c2[0] = bound(0.0f, c1[0], 1.0f);
10538 c2[1] = bound(0.0f, c1[1], 1.0f);
10539 c2[2] = bound(0.0f, c1[2], 1.0f);
10540 c2[3] = bound(0.0f, c1[3], 1.0f);
10544 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10554 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10555 rsurface.passcolor4f_vertexbuffer = 0;
10556 rsurface.passcolor4f_bufferoffset = 0;
10557 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)
10559 f = -DotProduct(r_refdef.view.forward, n);
10561 f = f * 0.85 + 0.15; // work around so stuff won't get black
10562 f *= r_refdef.lightmapintensity;
10563 Vector4Set(c, f, f, f, 1);
10567 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10569 RSurf_DrawBatch_GL11_ApplyFakeLight();
10570 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10571 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10572 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10573 GL_Color(r, g, b, a);
10577 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10585 vec3_t ambientcolor;
10586 vec3_t diffusecolor;
10590 VectorCopy(rsurface.modellight_lightdir, lightdir);
10591 f = 0.5f * r_refdef.lightmapintensity;
10592 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10593 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10594 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10595 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10596 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10597 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10599 if (VectorLength2(diffusecolor) > 0)
10601 // q3-style directional shading
10602 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10603 rsurface.passcolor4f_vertexbuffer = 0;
10604 rsurface.passcolor4f_bufferoffset = 0;
10605 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)
10607 if ((f = DotProduct(n, lightdir)) > 0)
10608 VectorMA(ambientcolor, f, diffusecolor, c);
10610 VectorCopy(ambientcolor, c);
10617 *applycolor = false;
10621 *r = ambientcolor[0];
10622 *g = ambientcolor[1];
10623 *b = ambientcolor[2];
10624 rsurface.passcolor4f = NULL;
10625 rsurface.passcolor4f_vertexbuffer = 0;
10626 rsurface.passcolor4f_bufferoffset = 0;
10630 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10632 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10633 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10634 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10635 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10636 GL_Color(r, g, b, a);
10640 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10648 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10649 rsurface.passcolor4f_vertexbuffer = 0;
10650 rsurface.passcolor4f_bufferoffset = 0;
10652 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10654 f = 1 - RSurf_FogVertex(v);
10662 void RSurf_SetupDepthAndCulling(void)
10664 // submodels are biased to avoid z-fighting with world surfaces that they
10665 // may be exactly overlapping (avoids z-fighting artifacts on certain
10666 // doors and things in Quake maps)
10667 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10668 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10669 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10670 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10673 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10675 // transparent sky would be ridiculous
10676 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10678 R_SetupShader_Generic_NoTexture(false, false);
10679 skyrenderlater = true;
10680 RSurf_SetupDepthAndCulling();
10681 GL_DepthMask(true);
10682 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10683 // skymasking on them, and Quake3 never did sky masking (unlike
10684 // software Quake and software Quake2), so disable the sky masking
10685 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10686 // and skymasking also looks very bad when noclipping outside the
10687 // level, so don't use it then either.
10688 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10690 R_Mesh_ResetTextureState();
10691 if (skyrendermasked)
10693 R_SetupShader_DepthOrShadow(false, false, false);
10694 // depth-only (masking)
10695 GL_ColorMask(0,0,0,0);
10696 // just to make sure that braindead drivers don't draw
10697 // anything despite that colormask...
10698 GL_BlendFunc(GL_ZERO, GL_ONE);
10699 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10700 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10704 R_SetupShader_Generic_NoTexture(false, false);
10706 GL_BlendFunc(GL_ONE, GL_ZERO);
10707 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10708 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10709 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10712 if (skyrendermasked)
10713 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10715 R_Mesh_ResetTextureState();
10716 GL_Color(1, 1, 1, 1);
10719 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10720 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10721 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10723 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10727 // render screenspace normalmap to texture
10728 GL_DepthMask(true);
10729 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10734 // bind lightmap texture
10736 // water/refraction/reflection/camera surfaces have to be handled specially
10737 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10739 int start, end, startplaneindex;
10740 for (start = 0;start < texturenumsurfaces;start = end)
10742 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10743 if(startplaneindex < 0)
10745 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10746 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10750 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10752 // now that we have a batch using the same planeindex, render it
10753 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10755 // render water or distortion background
10756 GL_DepthMask(true);
10757 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);
10759 // blend surface on top
10760 GL_DepthMask(false);
10761 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10764 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10766 // render surface with reflection texture as input
10767 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10768 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);
10775 // render surface batch normally
10776 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10777 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);
10781 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10783 // OpenGL 1.3 path - anything not completely ancient
10784 qboolean applycolor;
10787 const texturelayer_t *layer;
10788 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);
10789 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10791 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10794 int layertexrgbscale;
10795 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10797 if (layerindex == 0)
10798 GL_AlphaTest(true);
10801 GL_AlphaTest(false);
10802 GL_DepthFunc(GL_EQUAL);
10805 GL_DepthMask(layer->depthmask && writedepth);
10806 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10807 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10809 layertexrgbscale = 4;
10810 VectorScale(layer->color, 0.25f, layercolor);
10812 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10814 layertexrgbscale = 2;
10815 VectorScale(layer->color, 0.5f, layercolor);
10819 layertexrgbscale = 1;
10820 VectorScale(layer->color, 1.0f, layercolor);
10822 layercolor[3] = layer->color[3];
10823 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10824 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10825 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10826 switch (layer->type)
10828 case TEXTURELAYERTYPE_LITTEXTURE:
10829 // single-pass lightmapped texture with 2x rgbscale
10830 R_Mesh_TexBind(0, r_texture_white);
10831 R_Mesh_TexMatrix(0, NULL);
10832 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10833 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10834 R_Mesh_TexBind(1, layer->texture);
10835 R_Mesh_TexMatrix(1, &layer->texmatrix);
10836 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10837 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10838 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10839 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10840 else if (FAKELIGHT_ENABLED)
10841 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10842 else if (rsurface.uselightmaptexture)
10843 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10845 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10847 case TEXTURELAYERTYPE_TEXTURE:
10848 // singletexture unlit texture with transparency support
10849 R_Mesh_TexBind(0, layer->texture);
10850 R_Mesh_TexMatrix(0, &layer->texmatrix);
10851 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10852 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10853 R_Mesh_TexBind(1, 0);
10854 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10855 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10857 case TEXTURELAYERTYPE_FOG:
10858 // singletexture fogging
10859 if (layer->texture)
10861 R_Mesh_TexBind(0, layer->texture);
10862 R_Mesh_TexMatrix(0, &layer->texmatrix);
10863 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10864 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10868 R_Mesh_TexBind(0, 0);
10869 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10871 R_Mesh_TexBind(1, 0);
10872 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10873 // generate a color array for the fog pass
10874 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10875 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10879 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10882 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10884 GL_DepthFunc(GL_LEQUAL);
10885 GL_AlphaTest(false);
10889 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10891 // OpenGL 1.1 - crusty old voodoo path
10894 const texturelayer_t *layer;
10895 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);
10896 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10898 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10900 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10902 if (layerindex == 0)
10903 GL_AlphaTest(true);
10906 GL_AlphaTest(false);
10907 GL_DepthFunc(GL_EQUAL);
10910 GL_DepthMask(layer->depthmask && writedepth);
10911 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10912 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10913 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10914 switch (layer->type)
10916 case TEXTURELAYERTYPE_LITTEXTURE:
10917 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10919 // two-pass lit texture with 2x rgbscale
10920 // first the lightmap pass
10921 R_Mesh_TexBind(0, r_texture_white);
10922 R_Mesh_TexMatrix(0, NULL);
10923 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10924 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10925 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10926 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10927 else if (FAKELIGHT_ENABLED)
10928 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10929 else if (rsurface.uselightmaptexture)
10930 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10932 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10933 // then apply the texture to it
10934 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10935 R_Mesh_TexBind(0, layer->texture);
10936 R_Mesh_TexMatrix(0, &layer->texmatrix);
10937 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10938 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10939 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);
10943 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10944 R_Mesh_TexBind(0, layer->texture);
10945 R_Mesh_TexMatrix(0, &layer->texmatrix);
10946 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10947 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10948 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10949 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);
10950 else if (FAKELIGHT_ENABLED)
10951 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);
10953 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);
10956 case TEXTURELAYERTYPE_TEXTURE:
10957 // singletexture unlit texture with transparency support
10958 R_Mesh_TexBind(0, layer->texture);
10959 R_Mesh_TexMatrix(0, &layer->texmatrix);
10960 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10961 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10962 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);
10964 case TEXTURELAYERTYPE_FOG:
10965 // singletexture fogging
10966 if (layer->texture)
10968 R_Mesh_TexBind(0, layer->texture);
10969 R_Mesh_TexMatrix(0, &layer->texmatrix);
10970 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10971 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10975 R_Mesh_TexBind(0, 0);
10976 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10978 // generate a color array for the fog pass
10979 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10980 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10984 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10987 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10989 GL_DepthFunc(GL_LEQUAL);
10990 GL_AlphaTest(false);
10994 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10998 r_vertexgeneric_t *batchvertex;
11001 // R_Mesh_ResetTextureState();
11002 R_SetupShader_Generic_NoTexture(false, false);
11004 if(rsurface.texture && rsurface.texture->currentskinframe)
11006 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11007 c[3] *= rsurface.texture->currentalpha;
11017 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11019 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11020 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11021 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11024 // brighten it up (as texture value 127 means "unlit")
11025 c[0] *= 2 * r_refdef.view.colorscale;
11026 c[1] *= 2 * r_refdef.view.colorscale;
11027 c[2] *= 2 * r_refdef.view.colorscale;
11029 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11030 c[3] *= r_wateralpha.value;
11032 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11034 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11035 GL_DepthMask(false);
11037 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11039 GL_BlendFunc(GL_ONE, GL_ONE);
11040 GL_DepthMask(false);
11042 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11044 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11045 GL_DepthMask(false);
11047 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11049 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11050 GL_DepthMask(false);
11054 GL_BlendFunc(GL_ONE, GL_ZERO);
11055 GL_DepthMask(writedepth);
11058 if (r_showsurfaces.integer == 3)
11060 rsurface.passcolor4f = NULL;
11062 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11064 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11066 rsurface.passcolor4f = NULL;
11067 rsurface.passcolor4f_vertexbuffer = 0;
11068 rsurface.passcolor4f_bufferoffset = 0;
11070 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11072 qboolean applycolor = true;
11075 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11077 r_refdef.lightmapintensity = 1;
11078 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11079 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11081 else if (FAKELIGHT_ENABLED)
11083 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11085 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11086 RSurf_DrawBatch_GL11_ApplyFakeLight();
11087 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11091 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11093 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11094 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11095 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11098 if(!rsurface.passcolor4f)
11099 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11101 RSurf_DrawBatch_GL11_ApplyAmbient();
11102 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11103 if(r_refdef.fogenabled)
11104 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11105 RSurf_DrawBatch_GL11_ClampColor();
11107 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11108 R_SetupShader_Generic_NoTexture(false, false);
11111 else if (!r_refdef.view.showdebug)
11113 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11114 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11115 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11117 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11118 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11120 R_Mesh_PrepareVertices_Generic_Unlock();
11123 else if (r_showsurfaces.integer == 4)
11125 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11126 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11127 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11129 unsigned char c = (vi << 3) * (1.0f / 256.0f);
11130 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11131 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11133 R_Mesh_PrepareVertices_Generic_Unlock();
11136 else if (r_showsurfaces.integer == 2)
11139 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11140 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11141 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11143 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11144 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11145 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11146 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11147 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11148 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11149 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11151 R_Mesh_PrepareVertices_Generic_Unlock();
11152 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11156 int texturesurfaceindex;
11158 const msurface_t *surface;
11159 float surfacecolor4f[4];
11160 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11161 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11163 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11165 surface = texturesurfacelist[texturesurfaceindex];
11166 k = (int)(((size_t)surface) / sizeof(msurface_t));
11167 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11168 for (j = 0;j < surface->num_vertices;j++)
11170 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11171 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11175 R_Mesh_PrepareVertices_Generic_Unlock();
11180 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11183 RSurf_SetupDepthAndCulling();
11184 if (r_showsurfaces.integer)
11186 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11189 switch (vid.renderpath)
11191 case RENDERPATH_GL20:
11192 case RENDERPATH_D3D9:
11193 case RENDERPATH_D3D10:
11194 case RENDERPATH_D3D11:
11195 case RENDERPATH_SOFT:
11196 case RENDERPATH_GLES2:
11197 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11199 case RENDERPATH_GL13:
11200 case RENDERPATH_GLES1:
11201 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11203 case RENDERPATH_GL11:
11204 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11210 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11213 RSurf_SetupDepthAndCulling();
11214 if (r_showsurfaces.integer)
11216 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11219 switch (vid.renderpath)
11221 case RENDERPATH_GL20:
11222 case RENDERPATH_D3D9:
11223 case RENDERPATH_D3D10:
11224 case RENDERPATH_D3D11:
11225 case RENDERPATH_SOFT:
11226 case RENDERPATH_GLES2:
11227 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11229 case RENDERPATH_GL13:
11230 case RENDERPATH_GLES1:
11231 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11233 case RENDERPATH_GL11:
11234 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11240 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11243 int texturenumsurfaces, endsurface;
11244 texture_t *texture;
11245 const msurface_t *surface;
11246 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11248 // if the model is static it doesn't matter what value we give for
11249 // wantnormals and wanttangents, so this logic uses only rules applicable
11250 // to a model, knowing that they are meaningless otherwise
11251 if (ent == r_refdef.scene.worldentity)
11252 RSurf_ActiveWorldEntity();
11253 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11254 RSurf_ActiveModelEntity(ent, false, false, false);
11257 switch (vid.renderpath)
11259 case RENDERPATH_GL20:
11260 case RENDERPATH_D3D9:
11261 case RENDERPATH_D3D10:
11262 case RENDERPATH_D3D11:
11263 case RENDERPATH_SOFT:
11264 case RENDERPATH_GLES2:
11265 RSurf_ActiveModelEntity(ent, true, true, false);
11267 case RENDERPATH_GL11:
11268 case RENDERPATH_GL13:
11269 case RENDERPATH_GLES1:
11270 RSurf_ActiveModelEntity(ent, true, false, false);
11275 if (r_transparentdepthmasking.integer)
11277 qboolean setup = false;
11278 for (i = 0;i < numsurfaces;i = j)
11281 surface = rsurface.modelsurfaces + surfacelist[i];
11282 texture = surface->texture;
11283 rsurface.texture = R_GetCurrentTexture(texture);
11284 rsurface.lightmaptexture = NULL;
11285 rsurface.deluxemaptexture = NULL;
11286 rsurface.uselightmaptexture = false;
11287 // scan ahead until we find a different texture
11288 endsurface = min(i + 1024, numsurfaces);
11289 texturenumsurfaces = 0;
11290 texturesurfacelist[texturenumsurfaces++] = surface;
11291 for (;j < endsurface;j++)
11293 surface = rsurface.modelsurfaces + surfacelist[j];
11294 if (texture != surface->texture)
11296 texturesurfacelist[texturenumsurfaces++] = surface;
11298 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11300 // render the range of surfaces as depth
11304 GL_ColorMask(0,0,0,0);
11306 GL_DepthTest(true);
11307 GL_BlendFunc(GL_ONE, GL_ZERO);
11308 GL_DepthMask(true);
11309 // R_Mesh_ResetTextureState();
11311 RSurf_SetupDepthAndCulling();
11312 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11313 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11314 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11318 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11321 for (i = 0;i < numsurfaces;i = j)
11324 surface = rsurface.modelsurfaces + surfacelist[i];
11325 texture = surface->texture;
11326 rsurface.texture = R_GetCurrentTexture(texture);
11327 // scan ahead until we find a different texture
11328 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11329 texturenumsurfaces = 0;
11330 texturesurfacelist[texturenumsurfaces++] = surface;
11331 if(FAKELIGHT_ENABLED)
11333 rsurface.lightmaptexture = NULL;
11334 rsurface.deluxemaptexture = NULL;
11335 rsurface.uselightmaptexture = false;
11336 for (;j < endsurface;j++)
11338 surface = rsurface.modelsurfaces + surfacelist[j];
11339 if (texture != surface->texture)
11341 texturesurfacelist[texturenumsurfaces++] = surface;
11346 rsurface.lightmaptexture = surface->lightmaptexture;
11347 rsurface.deluxemaptexture = surface->deluxemaptexture;
11348 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11349 for (;j < endsurface;j++)
11351 surface = rsurface.modelsurfaces + surfacelist[j];
11352 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11354 texturesurfacelist[texturenumsurfaces++] = surface;
11357 // render the range of surfaces
11358 if (ent == r_refdef.scene.worldentity)
11359 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11361 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11363 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11366 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11368 // transparent surfaces get pushed off into the transparent queue
11369 int surfacelistindex;
11370 const msurface_t *surface;
11371 vec3_t tempcenter, center;
11372 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11374 surface = texturesurfacelist[surfacelistindex];
11375 if (r_transparent_sortsurfacesbynearest.integer)
11377 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11378 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11379 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11383 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11384 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11385 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11387 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11388 if (rsurface.entity->transparent_offset) // transparent offset
11390 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11391 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11392 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11394 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);
11398 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11400 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11402 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11404 RSurf_SetupDepthAndCulling();
11405 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11406 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11407 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11411 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11415 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11418 if (!rsurface.texture->currentnumlayers)
11420 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11421 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11423 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11425 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11426 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11427 else if (!rsurface.texture->currentnumlayers)
11429 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11431 // in the deferred case, transparent surfaces were queued during prepass
11432 if (!r_shadow_usingdeferredprepass)
11433 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11437 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11438 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11443 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11446 texture_t *texture;
11447 R_FrameData_SetMark();
11448 // break the surface list down into batches by texture and use of lightmapping
11449 for (i = 0;i < numsurfaces;i = j)
11452 // texture is the base texture pointer, rsurface.texture is the
11453 // current frame/skin the texture is directing us to use (for example
11454 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11455 // use skin 1 instead)
11456 texture = surfacelist[i]->texture;
11457 rsurface.texture = R_GetCurrentTexture(texture);
11458 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11460 // if this texture is not the kind we want, skip ahead to the next one
11461 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11465 if(FAKELIGHT_ENABLED || depthonly || prepass)
11467 rsurface.lightmaptexture = NULL;
11468 rsurface.deluxemaptexture = NULL;
11469 rsurface.uselightmaptexture = false;
11470 // simply scan ahead until we find a different texture or lightmap state
11471 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11476 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11477 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11478 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11479 // simply scan ahead until we find a different texture or lightmap state
11480 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11483 // render the range of surfaces
11484 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11486 R_FrameData_ReturnToMark();
11489 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11493 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11496 if (!rsurface.texture->currentnumlayers)
11498 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11499 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11501 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11503 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11504 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11505 else if (!rsurface.texture->currentnumlayers)
11507 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11509 // in the deferred case, transparent surfaces were queued during prepass
11510 if (!r_shadow_usingdeferredprepass)
11511 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11515 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11516 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11521 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11524 texture_t *texture;
11525 R_FrameData_SetMark();
11526 // break the surface list down into batches by texture and use of lightmapping
11527 for (i = 0;i < numsurfaces;i = j)
11530 // texture is the base texture pointer, rsurface.texture is the
11531 // current frame/skin the texture is directing us to use (for example
11532 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11533 // use skin 1 instead)
11534 texture = surfacelist[i]->texture;
11535 rsurface.texture = R_GetCurrentTexture(texture);
11536 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11538 // if this texture is not the kind we want, skip ahead to the next one
11539 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11543 if(FAKELIGHT_ENABLED || depthonly || prepass)
11545 rsurface.lightmaptexture = NULL;
11546 rsurface.deluxemaptexture = NULL;
11547 rsurface.uselightmaptexture = false;
11548 // simply scan ahead until we find a different texture or lightmap state
11549 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11554 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11555 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11556 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11557 // simply scan ahead until we find a different texture or lightmap state
11558 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11561 // render the range of surfaces
11562 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11564 R_FrameData_ReturnToMark();
11567 float locboxvertex3f[6*4*3] =
11569 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11570 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11571 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11572 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11573 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11574 1,0,0, 0,0,0, 0,1,0, 1,1,0
11577 unsigned short locboxelements[6*2*3] =
11582 12,13,14, 12,14,15,
11583 16,17,18, 16,18,19,
11587 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11590 cl_locnode_t *loc = (cl_locnode_t *)ent;
11592 float vertex3f[6*4*3];
11594 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11595 GL_DepthMask(false);
11596 GL_DepthRange(0, 1);
11597 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11598 GL_DepthTest(true);
11599 GL_CullFace(GL_NONE);
11600 R_EntityMatrix(&identitymatrix);
11602 // R_Mesh_ResetTextureState();
11604 i = surfacelist[0];
11605 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11606 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11607 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11608 surfacelist[0] < 0 ? 0.5f : 0.125f);
11610 if (VectorCompare(loc->mins, loc->maxs))
11612 VectorSet(size, 2, 2, 2);
11613 VectorMA(loc->mins, -0.5f, size, mins);
11617 VectorCopy(loc->mins, mins);
11618 VectorSubtract(loc->maxs, loc->mins, size);
11621 for (i = 0;i < 6*4*3;)
11622 for (j = 0;j < 3;j++, i++)
11623 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11625 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11626 R_SetupShader_Generic_NoTexture(false, false);
11627 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11630 void R_DrawLocs(void)
11633 cl_locnode_t *loc, *nearestloc;
11635 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11636 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11638 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11639 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11643 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11645 if (decalsystem->decals)
11646 Mem_Free(decalsystem->decals);
11647 memset(decalsystem, 0, sizeof(*decalsystem));
11650 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, unsigned int decalsequence)
11653 tridecal_t *decals;
11656 // expand or initialize the system
11657 if (decalsystem->maxdecals <= decalsystem->numdecals)
11659 decalsystem_t old = *decalsystem;
11660 qboolean useshortelements;
11661 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11662 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11663 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)));
11664 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11665 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11666 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11667 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11668 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11669 if (decalsystem->numdecals)
11670 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11672 Mem_Free(old.decals);
11673 for (i = 0;i < decalsystem->maxdecals*3;i++)
11674 decalsystem->element3i[i] = i;
11675 if (useshortelements)
11676 for (i = 0;i < decalsystem->maxdecals*3;i++)
11677 decalsystem->element3s[i] = i;
11680 // grab a decal and search for another free slot for the next one
11681 decals = decalsystem->decals;
11682 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11683 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11685 decalsystem->freedecal = i;
11686 if (decalsystem->numdecals <= i)
11687 decalsystem->numdecals = i + 1;
11689 // initialize the decal
11691 decal->triangleindex = triangleindex;
11692 decal->surfaceindex = surfaceindex;
11693 decal->decalsequence = decalsequence;
11694 decal->color4f[0][0] = c0[0];
11695 decal->color4f[0][1] = c0[1];
11696 decal->color4f[0][2] = c0[2];
11697 decal->color4f[0][3] = 1;
11698 decal->color4f[1][0] = c1[0];
11699 decal->color4f[1][1] = c1[1];
11700 decal->color4f[1][2] = c1[2];
11701 decal->color4f[1][3] = 1;
11702 decal->color4f[2][0] = c2[0];
11703 decal->color4f[2][1] = c2[1];
11704 decal->color4f[2][2] = c2[2];
11705 decal->color4f[2][3] = 1;
11706 decal->vertex3f[0][0] = v0[0];
11707 decal->vertex3f[0][1] = v0[1];
11708 decal->vertex3f[0][2] = v0[2];
11709 decal->vertex3f[1][0] = v1[0];
11710 decal->vertex3f[1][1] = v1[1];
11711 decal->vertex3f[1][2] = v1[2];
11712 decal->vertex3f[2][0] = v2[0];
11713 decal->vertex3f[2][1] = v2[1];
11714 decal->vertex3f[2][2] = v2[2];
11715 decal->texcoord2f[0][0] = t0[0];
11716 decal->texcoord2f[0][1] = t0[1];
11717 decal->texcoord2f[1][0] = t1[0];
11718 decal->texcoord2f[1][1] = t1[1];
11719 decal->texcoord2f[2][0] = t2[0];
11720 decal->texcoord2f[2][1] = t2[1];
11721 TriangleNormal(v0, v1, v2, decal->plane);
11722 VectorNormalize(decal->plane);
11723 decal->plane[3] = DotProduct(v0, decal->plane);
11726 extern cvar_t cl_decals_bias;
11727 extern cvar_t cl_decals_models;
11728 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11729 // baseparms, parms, temps
11730 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11735 const float *vertex3f;
11736 const float *normal3f;
11738 float points[2][9][3];
11745 e = rsurface.modelelement3i + 3*triangleindex;
11747 vertex3f = rsurface.modelvertex3f;
11748 normal3f = rsurface.modelnormal3f;
11752 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11754 index = 3*e[cornerindex];
11755 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11760 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11762 index = 3*e[cornerindex];
11763 VectorCopy(vertex3f + index, v[cornerindex]);
11768 //TriangleNormal(v[0], v[1], v[2], normal);
11769 //if (DotProduct(normal, localnormal) < 0.0f)
11771 // clip by each of the box planes formed from the projection matrix
11772 // if anything survives, we emit the decal
11773 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]);
11776 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]);
11779 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]);
11782 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]);
11785 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]);
11788 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]);
11791 // some part of the triangle survived, so we have to accept it...
11794 // dynamic always uses the original triangle
11796 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11798 index = 3*e[cornerindex];
11799 VectorCopy(vertex3f + index, v[cornerindex]);
11802 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11804 // convert vertex positions to texcoords
11805 Matrix4x4_Transform(projection, v[cornerindex], temp);
11806 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11807 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11808 // calculate distance fade from the projection origin
11809 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11810 f = bound(0.0f, f, 1.0f);
11811 c[cornerindex][0] = r * f;
11812 c[cornerindex][1] = g * f;
11813 c[cornerindex][2] = b * f;
11814 c[cornerindex][3] = 1.0f;
11815 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11818 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);
11820 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11821 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);
11823 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, unsigned int decalsequence)
11825 matrix4x4_t projection;
11826 decalsystem_t *decalsystem;
11829 const msurface_t *surface;
11830 const msurface_t *surfaces;
11831 const int *surfacelist;
11832 const texture_t *texture;
11834 int numsurfacelist;
11835 int surfacelistindex;
11838 float localorigin[3];
11839 float localnormal[3];
11840 float localmins[3];
11841 float localmaxs[3];
11844 float planes[6][4];
11847 int bih_triangles_count;
11848 int bih_triangles[256];
11849 int bih_surfaces[256];
11851 decalsystem = &ent->decalsystem;
11852 model = ent->model;
11853 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11855 R_DecalSystem_Reset(&ent->decalsystem);
11859 if (!model->brush.data_leafs && !cl_decals_models.integer)
11861 if (decalsystem->model)
11862 R_DecalSystem_Reset(decalsystem);
11866 if (decalsystem->model != model)
11867 R_DecalSystem_Reset(decalsystem);
11868 decalsystem->model = model;
11870 RSurf_ActiveModelEntity(ent, true, false, false);
11872 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11873 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11874 VectorNormalize(localnormal);
11875 localsize = worldsize*rsurface.inversematrixscale;
11876 localmins[0] = localorigin[0] - localsize;
11877 localmins[1] = localorigin[1] - localsize;
11878 localmins[2] = localorigin[2] - localsize;
11879 localmaxs[0] = localorigin[0] + localsize;
11880 localmaxs[1] = localorigin[1] + localsize;
11881 localmaxs[2] = localorigin[2] + localsize;
11883 //VectorCopy(localnormal, planes[4]);
11884 //VectorVectors(planes[4], planes[2], planes[0]);
11885 AnglesFromVectors(angles, localnormal, NULL, false);
11886 AngleVectors(angles, planes[0], planes[2], planes[4]);
11887 VectorNegate(planes[0], planes[1]);
11888 VectorNegate(planes[2], planes[3]);
11889 VectorNegate(planes[4], planes[5]);
11890 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11891 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11892 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11893 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11894 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11895 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11900 matrix4x4_t forwardprojection;
11901 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11902 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11907 float projectionvector[4][3];
11908 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11909 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11910 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11911 projectionvector[0][0] = planes[0][0] * ilocalsize;
11912 projectionvector[0][1] = planes[1][0] * ilocalsize;
11913 projectionvector[0][2] = planes[2][0] * ilocalsize;
11914 projectionvector[1][0] = planes[0][1] * ilocalsize;
11915 projectionvector[1][1] = planes[1][1] * ilocalsize;
11916 projectionvector[1][2] = planes[2][1] * ilocalsize;
11917 projectionvector[2][0] = planes[0][2] * ilocalsize;
11918 projectionvector[2][1] = planes[1][2] * ilocalsize;
11919 projectionvector[2][2] = planes[2][2] * ilocalsize;
11920 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11921 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11922 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11923 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11927 dynamic = model->surfmesh.isanimated;
11928 numsurfacelist = model->nummodelsurfaces;
11929 surfacelist = model->sortedmodelsurfaces;
11930 surfaces = model->data_surfaces;
11933 bih_triangles_count = -1;
11936 if(model->render_bih.numleafs)
11937 bih = &model->render_bih;
11938 else if(model->collision_bih.numleafs)
11939 bih = &model->collision_bih;
11942 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11943 if(bih_triangles_count == 0)
11945 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11947 if(bih_triangles_count > 0)
11949 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11951 surfaceindex = bih_surfaces[triangleindex];
11952 surface = surfaces + surfaceindex;
11953 texture = surface->texture;
11954 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11956 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11958 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11963 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11965 surfaceindex = surfacelist[surfacelistindex];
11966 surface = surfaces + surfaceindex;
11967 // check cull box first because it rejects more than any other check
11968 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11970 // skip transparent surfaces
11971 texture = surface->texture;
11972 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11974 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11976 numtriangles = surface->num_triangles;
11977 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11978 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11983 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11984 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, unsigned int decalsequence)
11986 int renderentityindex;
11987 float worldmins[3];
11988 float worldmaxs[3];
11989 entity_render_t *ent;
11991 if (!cl_decals_newsystem.integer)
11994 worldmins[0] = worldorigin[0] - worldsize;
11995 worldmins[1] = worldorigin[1] - worldsize;
11996 worldmins[2] = worldorigin[2] - worldsize;
11997 worldmaxs[0] = worldorigin[0] + worldsize;
11998 worldmaxs[1] = worldorigin[1] + worldsize;
11999 worldmaxs[2] = worldorigin[2] + worldsize;
12001 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12003 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12005 ent = r_refdef.scene.entities[renderentityindex];
12006 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12009 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12013 typedef struct r_decalsystem_splatqueue_s
12015 vec3_t worldorigin;
12016 vec3_t worldnormal;
12020 unsigned int decalsequence;
12022 r_decalsystem_splatqueue_t;
12024 int r_decalsystem_numqueued = 0;
12025 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12027 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)
12029 r_decalsystem_splatqueue_t *queue;
12031 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12034 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12035 VectorCopy(worldorigin, queue->worldorigin);
12036 VectorCopy(worldnormal, queue->worldnormal);
12037 Vector4Set(queue->color, r, g, b, a);
12038 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12039 queue->worldsize = worldsize;
12040 queue->decalsequence = cl.decalsequence++;
12043 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12046 r_decalsystem_splatqueue_t *queue;
12048 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12049 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);
12050 r_decalsystem_numqueued = 0;
12053 extern cvar_t cl_decals_max;
12054 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12057 decalsystem_t *decalsystem = &ent->decalsystem;
12059 unsigned int killsequence;
12064 if (!decalsystem->numdecals)
12067 if (r_showsurfaces.integer)
12070 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12072 R_DecalSystem_Reset(decalsystem);
12076 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12077 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12079 if (decalsystem->lastupdatetime)
12080 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12083 decalsystem->lastupdatetime = r_refdef.scene.time;
12084 numdecals = decalsystem->numdecals;
12086 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12088 if (decal->color4f[0][3])
12090 decal->lived += frametime;
12091 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12093 memset(decal, 0, sizeof(*decal));
12094 if (decalsystem->freedecal > i)
12095 decalsystem->freedecal = i;
12099 decal = decalsystem->decals;
12100 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12103 // collapse the array by shuffling the tail decals into the gaps
12106 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12107 decalsystem->freedecal++;
12108 if (decalsystem->freedecal == numdecals)
12110 decal[decalsystem->freedecal] = decal[--numdecals];
12113 decalsystem->numdecals = numdecals;
12115 if (numdecals <= 0)
12117 // if there are no decals left, reset decalsystem
12118 R_DecalSystem_Reset(decalsystem);
12122 extern skinframe_t *decalskinframe;
12123 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12126 decalsystem_t *decalsystem = &ent->decalsystem;
12135 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12138 numdecals = decalsystem->numdecals;
12142 if (r_showsurfaces.integer)
12145 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12147 R_DecalSystem_Reset(decalsystem);
12151 // if the model is static it doesn't matter what value we give for
12152 // wantnormals and wanttangents, so this logic uses only rules applicable
12153 // to a model, knowing that they are meaningless otherwise
12154 if (ent == r_refdef.scene.worldentity)
12155 RSurf_ActiveWorldEntity();
12157 RSurf_ActiveModelEntity(ent, false, false, false);
12159 decalsystem->lastupdatetime = r_refdef.scene.time;
12161 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12163 // update vertex positions for animated models
12164 v3f = decalsystem->vertex3f;
12165 c4f = decalsystem->color4f;
12166 t2f = decalsystem->texcoord2f;
12167 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12169 if (!decal->color4f[0][3])
12172 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12176 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12179 // update color values for fading decals
12180 if (decal->lived >= cl_decals_time.value)
12181 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12185 c4f[ 0] = decal->color4f[0][0] * alpha;
12186 c4f[ 1] = decal->color4f[0][1] * alpha;
12187 c4f[ 2] = decal->color4f[0][2] * alpha;
12189 c4f[ 4] = decal->color4f[1][0] * alpha;
12190 c4f[ 5] = decal->color4f[1][1] * alpha;
12191 c4f[ 6] = decal->color4f[1][2] * alpha;
12193 c4f[ 8] = decal->color4f[2][0] * alpha;
12194 c4f[ 9] = decal->color4f[2][1] * alpha;
12195 c4f[10] = decal->color4f[2][2] * alpha;
12198 t2f[0] = decal->texcoord2f[0][0];
12199 t2f[1] = decal->texcoord2f[0][1];
12200 t2f[2] = decal->texcoord2f[1][0];
12201 t2f[3] = decal->texcoord2f[1][1];
12202 t2f[4] = decal->texcoord2f[2][0];
12203 t2f[5] = decal->texcoord2f[2][1];
12205 // update vertex positions for animated models
12206 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12208 e = rsurface.modelelement3i + 3*decal->triangleindex;
12209 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12210 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12211 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12215 VectorCopy(decal->vertex3f[0], v3f);
12216 VectorCopy(decal->vertex3f[1], v3f + 3);
12217 VectorCopy(decal->vertex3f[2], v3f + 6);
12220 if (r_refdef.fogenabled)
12222 alpha = RSurf_FogVertex(v3f);
12223 VectorScale(c4f, alpha, c4f);
12224 alpha = RSurf_FogVertex(v3f + 3);
12225 VectorScale(c4f + 4, alpha, c4f + 4);
12226 alpha = RSurf_FogVertex(v3f + 6);
12227 VectorScale(c4f + 8, alpha, c4f + 8);
12238 r_refdef.stats[r_stat_drawndecals] += numtris;
12240 // now render the decals all at once
12241 // (this assumes they all use one particle font texture!)
12242 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);
12243 // R_Mesh_ResetTextureState();
12244 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12245 GL_DepthMask(false);
12246 GL_DepthRange(0, 1);
12247 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12248 GL_DepthTest(true);
12249 GL_CullFace(GL_NONE);
12250 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12251 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12252 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12256 static void R_DrawModelDecals(void)
12260 // fade faster when there are too many decals
12261 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12262 for (i = 0;i < r_refdef.scene.numentities;i++)
12263 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12265 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12266 for (i = 0;i < r_refdef.scene.numentities;i++)
12267 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12268 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12270 R_DecalSystem_ApplySplatEntitiesQueue();
12272 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12273 for (i = 0;i < r_refdef.scene.numentities;i++)
12274 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12276 r_refdef.stats[r_stat_totaldecals] += numdecals;
12278 if (r_showsurfaces.integer)
12281 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12283 for (i = 0;i < r_refdef.scene.numentities;i++)
12285 if (!r_refdef.viewcache.entityvisible[i])
12287 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12288 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12292 extern cvar_t mod_collision_bih;
12293 static void R_DrawDebugModel(void)
12295 entity_render_t *ent = rsurface.entity;
12296 int i, j, flagsmask;
12297 const msurface_t *surface;
12298 dp_model_t *model = ent->model;
12300 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12303 if (r_showoverdraw.value > 0)
12305 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12306 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12307 R_SetupShader_Generic_NoTexture(false, false);
12308 GL_DepthTest(false);
12309 GL_DepthMask(false);
12310 GL_DepthRange(0, 1);
12311 GL_BlendFunc(GL_ONE, GL_ONE);
12312 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12314 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12316 rsurface.texture = R_GetCurrentTexture(surface->texture);
12317 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12319 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12320 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12321 if (!rsurface.texture->currentlayers->depthmask)
12322 GL_Color(c, 0, 0, 1.0f);
12323 else if (ent == r_refdef.scene.worldentity)
12324 GL_Color(c, c, c, 1.0f);
12326 GL_Color(0, c, 0, 1.0f);
12327 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12331 rsurface.texture = NULL;
12334 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12336 // R_Mesh_ResetTextureState();
12337 R_SetupShader_Generic_NoTexture(false, false);
12338 GL_DepthRange(0, 1);
12339 GL_DepthTest(!r_showdisabledepthtest.integer);
12340 GL_DepthMask(false);
12341 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12343 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12347 qboolean cullbox = false;
12348 const q3mbrush_t *brush;
12349 const bih_t *bih = &model->collision_bih;
12350 const bih_leaf_t *bihleaf;
12351 float vertex3f[3][3];
12352 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12353 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12355 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12357 switch (bihleaf->type)
12360 brush = model->brush.data_brushes + bihleaf->itemindex;
12361 if (brush->colbrushf && brush->colbrushf->numtriangles)
12363 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);
12364 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12365 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12368 case BIH_COLLISIONTRIANGLE:
12369 triangleindex = bihleaf->itemindex;
12370 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12371 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12372 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12373 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);
12374 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12375 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12377 case BIH_RENDERTRIANGLE:
12378 triangleindex = bihleaf->itemindex;
12379 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12380 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12381 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12382 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);
12383 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12384 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12390 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12393 if (r_showtris.integer && qglPolygonMode)
12395 if (r_showdisabledepthtest.integer)
12397 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12398 GL_DepthMask(false);
12402 GL_BlendFunc(GL_ONE, GL_ZERO);
12403 GL_DepthMask(true);
12405 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12406 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12408 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12410 rsurface.texture = R_GetCurrentTexture(surface->texture);
12411 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12413 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12414 if (!rsurface.texture->currentlayers->depthmask)
12415 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12416 else if (ent == r_refdef.scene.worldentity)
12417 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12419 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12420 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12424 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12425 rsurface.texture = NULL;
12428 if (r_shownormals.value != 0 && qglBegin)
12432 if (r_showdisabledepthtest.integer)
12434 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12435 GL_DepthMask(false);
12439 GL_BlendFunc(GL_ONE, GL_ZERO);
12440 GL_DepthMask(true);
12442 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12444 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12446 rsurface.texture = R_GetCurrentTexture(surface->texture);
12447 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12449 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12450 qglBegin(GL_LINES);
12451 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12453 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12455 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12456 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12457 qglVertex3f(v[0], v[1], v[2]);
12458 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12459 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12460 qglVertex3f(v[0], v[1], v[2]);
12463 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12465 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12467 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12468 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12469 qglVertex3f(v[0], v[1], v[2]);
12470 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12471 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12472 qglVertex3f(v[0], v[1], v[2]);
12475 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12477 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12479 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12480 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12481 qglVertex3f(v[0], v[1], v[2]);
12482 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12483 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12484 qglVertex3f(v[0], v[1], v[2]);
12487 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12489 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12491 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12492 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12493 qglVertex3f(v[0], v[1], v[2]);
12494 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12495 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12496 qglVertex3f(v[0], v[1], v[2]);
12503 rsurface.texture = NULL;
12508 int r_maxsurfacelist = 0;
12509 const msurface_t **r_surfacelist = NULL;
12510 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12512 int i, j, endj, flagsmask;
12513 dp_model_t *model = r_refdef.scene.worldmodel;
12514 msurface_t *surfaces;
12515 unsigned char *update;
12516 int numsurfacelist = 0;
12520 if (r_maxsurfacelist < model->num_surfaces)
12522 r_maxsurfacelist = model->num_surfaces;
12524 Mem_Free((msurface_t**)r_surfacelist);
12525 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12528 RSurf_ActiveWorldEntity();
12530 surfaces = model->data_surfaces;
12531 update = model->brushq1.lightmapupdateflags;
12533 // update light styles on this submodel
12534 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12536 model_brush_lightstyleinfo_t *style;
12537 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12539 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12541 int *list = style->surfacelist;
12542 style->value = r_refdef.scene.lightstylevalue[style->style];
12543 for (j = 0;j < style->numsurfaces;j++)
12544 update[list[j]] = true;
12549 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12553 R_DrawDebugModel();
12554 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12558 rsurface.lightmaptexture = NULL;
12559 rsurface.deluxemaptexture = NULL;
12560 rsurface.uselightmaptexture = false;
12561 rsurface.texture = NULL;
12562 rsurface.rtlight = NULL;
12563 numsurfacelist = 0;
12564 // add visible surfaces to draw list
12565 for (i = 0;i < model->nummodelsurfaces;i++)
12567 j = model->sortedmodelsurfaces[i];
12568 if (r_refdef.viewcache.world_surfacevisible[j])
12569 r_surfacelist[numsurfacelist++] = surfaces + j;
12571 // update lightmaps if needed
12572 if (model->brushq1.firstrender)
12574 model->brushq1.firstrender = false;
12575 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12577 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12581 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12582 if (r_refdef.viewcache.world_surfacevisible[j])
12584 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12586 // don't do anything if there were no surfaces
12587 if (!numsurfacelist)
12589 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12592 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12594 // add to stats if desired
12595 if (r_speeds.integer && !skysurfaces && !depthonly)
12597 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12598 for (j = 0;j < numsurfacelist;j++)
12599 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12602 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12605 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12607 int i, j, endj, flagsmask;
12608 dp_model_t *model = ent->model;
12609 msurface_t *surfaces;
12610 unsigned char *update;
12611 int numsurfacelist = 0;
12615 if (r_maxsurfacelist < model->num_surfaces)
12617 r_maxsurfacelist = model->num_surfaces;
12619 Mem_Free((msurface_t **)r_surfacelist);
12620 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12623 // if the model is static it doesn't matter what value we give for
12624 // wantnormals and wanttangents, so this logic uses only rules applicable
12625 // to a model, knowing that they are meaningless otherwise
12626 if (ent == r_refdef.scene.worldentity)
12627 RSurf_ActiveWorldEntity();
12628 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12629 RSurf_ActiveModelEntity(ent, false, false, false);
12631 RSurf_ActiveModelEntity(ent, true, true, true);
12632 else if (depthonly)
12634 switch (vid.renderpath)
12636 case RENDERPATH_GL20:
12637 case RENDERPATH_D3D9:
12638 case RENDERPATH_D3D10:
12639 case RENDERPATH_D3D11:
12640 case RENDERPATH_SOFT:
12641 case RENDERPATH_GLES2:
12642 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12644 case RENDERPATH_GL11:
12645 case RENDERPATH_GL13:
12646 case RENDERPATH_GLES1:
12647 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12653 switch (vid.renderpath)
12655 case RENDERPATH_GL20:
12656 case RENDERPATH_D3D9:
12657 case RENDERPATH_D3D10:
12658 case RENDERPATH_D3D11:
12659 case RENDERPATH_SOFT:
12660 case RENDERPATH_GLES2:
12661 RSurf_ActiveModelEntity(ent, true, true, false);
12663 case RENDERPATH_GL11:
12664 case RENDERPATH_GL13:
12665 case RENDERPATH_GLES1:
12666 RSurf_ActiveModelEntity(ent, true, false, false);
12671 surfaces = model->data_surfaces;
12672 update = model->brushq1.lightmapupdateflags;
12674 // update light styles
12675 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12677 model_brush_lightstyleinfo_t *style;
12678 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12680 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12682 int *list = style->surfacelist;
12683 style->value = r_refdef.scene.lightstylevalue[style->style];
12684 for (j = 0;j < style->numsurfaces;j++)
12685 update[list[j]] = true;
12690 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12694 R_DrawDebugModel();
12695 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12699 rsurface.lightmaptexture = NULL;
12700 rsurface.deluxemaptexture = NULL;
12701 rsurface.uselightmaptexture = false;
12702 rsurface.texture = NULL;
12703 rsurface.rtlight = NULL;
12704 numsurfacelist = 0;
12705 // add visible surfaces to draw list
12706 for (i = 0;i < model->nummodelsurfaces;i++)
12707 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12708 // don't do anything if there were no surfaces
12709 if (!numsurfacelist)
12711 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12714 // update lightmaps if needed
12718 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12723 R_BuildLightMap(ent, surfaces + j);
12728 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12730 // add to stats if desired
12731 if (r_speeds.integer && !skysurfaces && !depthonly)
12733 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12734 for (j = 0;j < numsurfacelist;j++)
12735 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12738 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12741 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12743 static texture_t texture;
12744 static msurface_t surface;
12745 const msurface_t *surfacelist = &surface;
12747 // fake enough texture and surface state to render this geometry
12749 texture.update_lastrenderframe = -1; // regenerate this texture
12750 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12751 texture.basealpha = 1.0f;
12752 texture.currentskinframe = skinframe;
12753 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12754 texture.offsetmapping = OFFSETMAPPING_OFF;
12755 texture.offsetscale = 1;
12756 texture.specularscalemod = 1;
12757 texture.specularpowermod = 1;
12758 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12759 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12760 // JUST GREP FOR "specularscalemod = 1".
12762 surface.texture = &texture;
12763 surface.num_triangles = numtriangles;
12764 surface.num_firsttriangle = firsttriangle;
12765 surface.num_vertices = numvertices;
12766 surface.num_firstvertex = firstvertex;
12769 rsurface.texture = R_GetCurrentTexture(surface.texture);
12770 rsurface.lightmaptexture = NULL;
12771 rsurface.deluxemaptexture = NULL;
12772 rsurface.uselightmaptexture = false;
12773 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12776 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)
12778 static msurface_t surface;
12779 const msurface_t *surfacelist = &surface;
12781 // fake enough texture and surface state to render this geometry
12782 surface.texture = texture;
12783 surface.num_triangles = numtriangles;
12784 surface.num_firsttriangle = firsttriangle;
12785 surface.num_vertices = numvertices;
12786 surface.num_firstvertex = firstvertex;
12789 rsurface.texture = R_GetCurrentTexture(surface.texture);
12790 rsurface.lightmaptexture = NULL;
12791 rsurface.deluxemaptexture = NULL;
12792 rsurface.uselightmaptexture = false;
12793 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);