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.
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
65 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!"};
66 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!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 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)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 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"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 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 (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 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) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84 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"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 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"};
92 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"};
93 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"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
97 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)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 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"};
101 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"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 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"};
104 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"};
105 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"};
106 cvar_t r_showspriteedges = {0, "r_showspriteedges", "0", "renders a debug outline to show the polygon shape of each sprite frame rendered (may be 2 or more in case of interpolated animations), for debugging rendering bugs with specific view types"};
107 cvar_t r_showparticleedges = {0, "r_showparticleedges", "0", "renders a debug outline to show the polygon shape of each particle, for debugging rendering bugs with specific view types"};
108 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
109 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
110 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
111 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
112 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
113 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
114 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
115 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
116 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)"};
117 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)"};
118 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
119 cvar_t r_cullentities_trace_expand = {0, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
120 cvar_t r_cullentities_trace_pad = {0, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
121 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
122 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
123 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
124 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
125 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
127 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
128 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
129 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
131 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
132 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
133 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
134 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
135 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
137 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
138 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
139 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
140 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."};
141 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
142 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
143 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
144 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."};
145 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
146 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
147 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
148 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."};
149 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
150 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"};
151 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"};
152 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
153 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
154 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
155 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
156 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
157 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"};
158 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
159 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
160 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
161 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
162 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
164 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
165 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
166 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
167 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
168 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
169 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
170 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
171 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
173 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)"};
174 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"};
176 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
177 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
178 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
180 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"};
181 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"};
182 cvar_t r_rendertarget_debug = {0, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"};
183 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"};
184 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
185 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
186 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"};
187 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)"};
188 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)"};
189 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
191 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
192 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)"};
193 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
194 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)"};
195 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
196 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)"};
197 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)"};
198 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
199 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"};
200 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."};
201 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206 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)"};
207 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)"};
208 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)"};
209 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)"};
211 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)"};
212 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)"};
213 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
214 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"};
215 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
216 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
217 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
218 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"};
219 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"};
221 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
222 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
223 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
224 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
226 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
227 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
229 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
230 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
231 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
232 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
233 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
234 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
236 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
237 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
238 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
239 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
240 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
241 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
242 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
243 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
244 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
245 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
247 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"};
249 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"};
251 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
253 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
255 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)"};
256 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)"};
257 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
258 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
260 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
261 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"};
263 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."};
265 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)"};
266 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
268 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
269 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
270 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
271 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
274 extern cvar_t v_glslgamma_2d;
276 extern qboolean v_flipped_state;
278 r_framebufferstate_t r_fb;
280 /// shadow volume bsp struct with automatically growing nodes buffer
283 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
285 rtexture_t *r_texture_blanknormalmap;
286 rtexture_t *r_texture_white;
287 rtexture_t *r_texture_grey128;
288 rtexture_t *r_texture_black;
289 rtexture_t *r_texture_notexture;
290 rtexture_t *r_texture_whitecube;
291 rtexture_t *r_texture_normalizationcube;
292 rtexture_t *r_texture_fogattenuation;
293 rtexture_t *r_texture_fogheighttexture;
294 rtexture_t *r_texture_gammaramps;
295 unsigned int r_texture_gammaramps_serial;
296 //rtexture_t *r_texture_fogintensity;
297 rtexture_t *r_texture_reflectcube;
299 // TODO: hash lookups?
300 typedef struct cubemapinfo_s
307 int r_texture_numcubemaps;
308 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
310 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
311 unsigned int r_numqueries;
312 unsigned int r_maxqueries;
314 typedef struct r_qwskincache_s
316 char name[MAX_QPATH];
317 skinframe_t *skinframe;
321 static r_qwskincache_t *r_qwskincache;
322 static int r_qwskincache_size;
324 /// vertex coordinates for a quad that covers the screen exactly
325 extern const float r_screenvertex3f[12];
326 const float r_screenvertex3f[12] =
334 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
337 for (i = 0;i < verts;i++)
348 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
351 for (i = 0;i < verts;i++)
361 // FIXME: move this to client?
364 if (gamemode == GAME_NEHAHRA)
366 Cvar_Set("gl_fogenable", "0");
367 Cvar_Set("gl_fogdensity", "0.2");
368 Cvar_Set("gl_fogred", "0.3");
369 Cvar_Set("gl_foggreen", "0.3");
370 Cvar_Set("gl_fogblue", "0.3");
372 r_refdef.fog_density = 0;
373 r_refdef.fog_red = 0;
374 r_refdef.fog_green = 0;
375 r_refdef.fog_blue = 0;
376 r_refdef.fog_alpha = 1;
377 r_refdef.fog_start = 0;
378 r_refdef.fog_end = 16384;
379 r_refdef.fog_height = 1<<30;
380 r_refdef.fog_fadedepth = 128;
381 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
384 static void R_BuildBlankTextures(void)
386 unsigned char data[4];
387 data[2] = 128; // normal X
388 data[1] = 128; // normal Y
389 data[0] = 255; // normal Z
390 data[3] = 255; // height
391 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
409 static void R_BuildNoTexture(void)
412 unsigned char pix[16][16][4];
413 // this makes a light grey/dark grey checkerboard texture
414 for (y = 0;y < 16;y++)
416 for (x = 0;x < 16;x++)
418 if ((y < 8) ^ (x < 8))
434 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
437 static void R_BuildWhiteCube(void)
439 unsigned char data[6*1*1*4];
440 memset(data, 255, sizeof(data));
441 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
444 static void R_BuildNormalizationCube(void)
448 vec_t s, t, intensity;
451 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
452 for (side = 0;side < 6;side++)
454 for (y = 0;y < NORMSIZE;y++)
456 for (x = 0;x < NORMSIZE;x++)
458 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
494 intensity = 127.0f / sqrt(DotProduct(v, v));
495 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
496 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
497 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
498 data[((side*64+y)*64+x)*4+3] = 255;
502 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
506 static void R_BuildFogTexture(void)
510 unsigned char data1[FOGWIDTH][4];
511 //unsigned char data2[FOGWIDTH][4];
514 r_refdef.fogmasktable_start = r_refdef.fog_start;
515 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
516 r_refdef.fogmasktable_range = r_refdef.fogrange;
517 r_refdef.fogmasktable_density = r_refdef.fog_density;
519 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
520 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
522 d = (x * r - r_refdef.fogmasktable_start);
523 if(developer_extra.integer)
524 Con_DPrintf("%f ", d);
526 if (r_fog_exp2.integer)
527 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
529 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
530 if(developer_extra.integer)
531 Con_DPrintf(" : %f ", alpha);
532 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
533 if(developer_extra.integer)
534 Con_DPrintf(" = %f\n", alpha);
535 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
538 for (x = 0;x < FOGWIDTH;x++)
540 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
545 //data2[x][0] = 255 - b;
546 //data2[x][1] = 255 - b;
547 //data2[x][2] = 255 - b;
550 if (r_texture_fogattenuation)
552 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
553 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
557 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
558 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
562 static void R_BuildFogHeightTexture(void)
564 unsigned char *inpixels;
572 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
573 if (r_refdef.fogheighttexturename[0])
574 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
577 r_refdef.fog_height_tablesize = 0;
578 if (r_texture_fogheighttexture)
579 R_FreeTexture(r_texture_fogheighttexture);
580 r_texture_fogheighttexture = NULL;
581 if (r_refdef.fog_height_table2d)
582 Mem_Free(r_refdef.fog_height_table2d);
583 r_refdef.fog_height_table2d = NULL;
584 if (r_refdef.fog_height_table1d)
585 Mem_Free(r_refdef.fog_height_table1d);
586 r_refdef.fog_height_table1d = NULL;
590 r_refdef.fog_height_tablesize = size;
591 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
592 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
593 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
595 // LordHavoc: now the magic - what is that table2d for? it is a cooked
596 // average fog color table accounting for every fog layer between a point
597 // and the camera. (Note: attenuation is handled separately!)
598 for (y = 0;y < size;y++)
600 for (x = 0;x < size;x++)
606 for (j = x;j <= y;j++)
608 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
614 for (j = x;j >= y;j--)
616 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
621 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
622 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
623 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
624 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
627 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
630 //=======================================================================================================================================================
632 static const char *builtinshaderstrings[] =
634 #include "shader_glsl.h"
638 const char *builtinhlslshaderstrings[] =
640 #include "shader_hlsl.h"
644 //=======================================================================================================================================================
646 typedef struct shaderpermutationinfo_s
651 shaderpermutationinfo_t;
653 typedef struct shadermodeinfo_s
655 const char *sourcebasename;
656 const char *extension;
657 const char **builtinshaderstrings;
666 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
667 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
669 {"#define USEDIFFUSE\n", " diffuse"},
670 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
671 {"#define USEVIEWTINT\n", " viewtint"},
672 {"#define USECOLORMAPPING\n", " colormapping"},
673 {"#define USESATURATION\n", " saturation"},
674 {"#define USEFOGINSIDE\n", " foginside"},
675 {"#define USEFOGOUTSIDE\n", " fogoutside"},
676 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
677 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
678 {"#define USEGAMMARAMPS\n", " gammaramps"},
679 {"#define USECUBEFILTER\n", " cubefilter"},
680 {"#define USEGLOW\n", " glow"},
681 {"#define USEBLOOM\n", " bloom"},
682 {"#define USESPECULAR\n", " specular"},
683 {"#define USEPOSTPROCESSING\n", " postprocessing"},
684 {"#define USEREFLECTION\n", " reflection"},
685 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
686 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
687 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
688 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
689 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
690 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
691 {"#define USEALPHAKILL\n", " alphakill"},
692 {"#define USEREFLECTCUBE\n", " reflectcube"},
693 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
694 {"#define USEBOUNCEGRID\n", " bouncegrid"},
695 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
696 {"#define USETRIPPY\n", " trippy"},
697 {"#define USEDEPTHRGB\n", " depthrgb"},
698 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
699 {"#define USESKELETAL\n", " skeletal"},
700 {"#define USEOCCLUDE\n", " occlude"}
703 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
704 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
706 // SHADERLANGUAGE_GLSL
708 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
709 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
721 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
722 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
723 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 // SHADERLANGUAGE_HLSL
728 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
729 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
730 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
731 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
732 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
741 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
742 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
743 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
744 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
748 struct r_glsl_permutation_s;
749 typedef struct r_glsl_permutation_s
752 struct r_glsl_permutation_s *hashnext;
754 dpuint64 permutation;
756 /// indicates if we have tried compiling this permutation already
758 /// 0 if compilation failed
760 // texture units assigned to each detected uniform
761 int tex_Texture_First;
762 int tex_Texture_Second;
763 int tex_Texture_GammaRamps;
764 int tex_Texture_Normal;
765 int tex_Texture_Color;
766 int tex_Texture_Gloss;
767 int tex_Texture_Glow;
768 int tex_Texture_SecondaryNormal;
769 int tex_Texture_SecondaryColor;
770 int tex_Texture_SecondaryGloss;
771 int tex_Texture_SecondaryGlow;
772 int tex_Texture_Pants;
773 int tex_Texture_Shirt;
774 int tex_Texture_FogHeightTexture;
775 int tex_Texture_FogMask;
776 int tex_Texture_Lightmap;
777 int tex_Texture_Deluxemap;
778 int tex_Texture_Attenuation;
779 int tex_Texture_Cube;
780 int tex_Texture_Refraction;
781 int tex_Texture_Reflection;
782 int tex_Texture_ShadowMap2D;
783 int tex_Texture_CubeProjection;
784 int tex_Texture_ScreenNormalMap;
785 int tex_Texture_ScreenDiffuse;
786 int tex_Texture_ScreenSpecular;
787 int tex_Texture_ReflectMask;
788 int tex_Texture_ReflectCube;
789 int tex_Texture_BounceGrid;
790 /// locations of detected uniforms in program object, or -1 if not found
791 int loc_Texture_First;
792 int loc_Texture_Second;
793 int loc_Texture_GammaRamps;
794 int loc_Texture_Normal;
795 int loc_Texture_Color;
796 int loc_Texture_Gloss;
797 int loc_Texture_Glow;
798 int loc_Texture_SecondaryNormal;
799 int loc_Texture_SecondaryColor;
800 int loc_Texture_SecondaryGloss;
801 int loc_Texture_SecondaryGlow;
802 int loc_Texture_Pants;
803 int loc_Texture_Shirt;
804 int loc_Texture_FogHeightTexture;
805 int loc_Texture_FogMask;
806 int loc_Texture_Lightmap;
807 int loc_Texture_Deluxemap;
808 int loc_Texture_Attenuation;
809 int loc_Texture_Cube;
810 int loc_Texture_Refraction;
811 int loc_Texture_Reflection;
812 int loc_Texture_ShadowMap2D;
813 int loc_Texture_CubeProjection;
814 int loc_Texture_ScreenNormalMap;
815 int loc_Texture_ScreenDiffuse;
816 int loc_Texture_ScreenSpecular;
817 int loc_Texture_ReflectMask;
818 int loc_Texture_ReflectCube;
819 int loc_Texture_BounceGrid;
821 int loc_BloomBlur_Parameters;
823 int loc_Color_Ambient;
824 int loc_Color_Diffuse;
825 int loc_Color_Specular;
829 int loc_DeferredColor_Ambient;
830 int loc_DeferredColor_Diffuse;
831 int loc_DeferredColor_Specular;
832 int loc_DeferredMod_Diffuse;
833 int loc_DeferredMod_Specular;
834 int loc_DistortScaleRefractReflect;
837 int loc_FogHeightFade;
839 int loc_FogPlaneViewDist;
840 int loc_FogRangeRecip;
843 int loc_LightPosition;
844 int loc_OffsetMapping_ScaleSteps;
845 int loc_OffsetMapping_LodDistance;
846 int loc_OffsetMapping_Bias;
848 int loc_ReflectColor;
849 int loc_ReflectFactor;
850 int loc_ReflectOffset;
851 int loc_RefractColor;
853 int loc_ScreenCenterRefractReflect;
854 int loc_ScreenScaleRefractReflect;
855 int loc_ScreenToDepth;
856 int loc_ShadowMap_Parameters;
857 int loc_ShadowMap_TextureScale;
858 int loc_SpecularPower;
859 int loc_Skeletal_Transform12;
864 int loc_ViewTintColor;
866 int loc_ModelToLight;
868 int loc_BackgroundTexMatrix;
869 int loc_ModelViewProjectionMatrix;
870 int loc_ModelViewMatrix;
871 int loc_PixelToScreenTexCoord;
872 int loc_ModelToReflectCube;
873 int loc_ShadowMapMatrix;
874 int loc_BloomColorSubtract;
875 int loc_NormalmapScrollBlend;
876 int loc_BounceGridMatrix;
877 int loc_BounceGridIntensity;
878 /// uniform block bindings
879 int ubibind_Skeletal_Transform12_UniformBlock;
880 /// uniform block indices
881 int ubiloc_Skeletal_Transform12_UniformBlock;
883 r_glsl_permutation_t;
885 #define SHADERPERMUTATION_HASHSIZE 256
888 // non-degradable "lightweight" shader parameters to keep the permutations simpler
889 // these can NOT degrade! only use for simple stuff
892 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
893 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
894 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
895 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
896 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
897 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
898 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
899 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
900 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
901 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
902 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
903 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
904 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
905 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
907 #define SHADERSTATICPARMS_COUNT 14
909 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
910 static int shaderstaticparms_count = 0;
912 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
913 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
915 extern qboolean r_shadow_shadowmapsampler;
916 extern int r_shadow_shadowmappcf;
917 qboolean R_CompileShader_CheckStaticParms(void)
919 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
920 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
921 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
924 if (r_glsl_saturation_redcompensate.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
926 if (r_glsl_vertextextureblend_usebothalphas.integer)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
928 if (r_shadow_glossexact.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
930 if (r_glsl_postprocess.integer)
932 if (r_glsl_postprocess_uservec1_enable.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
934 if (r_glsl_postprocess_uservec2_enable.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
936 if (r_glsl_postprocess_uservec3_enable.integer)
937 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
938 if (r_glsl_postprocess_uservec4_enable.integer)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
942 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
943 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
944 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
946 if (r_shadow_shadowmapsampler)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
948 if (r_shadow_shadowmappcf > 1)
949 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
950 else if (r_shadow_shadowmappcf)
951 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
952 if (r_celshading.integer)
953 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
954 if (r_celoutlines.integer)
955 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
957 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
960 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
961 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
962 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
964 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
965 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
967 shaderstaticparms_count = 0;
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
980 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
981 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
982 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
983 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
986 /// information about each possible shader permutation
987 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
988 /// currently selected permutation
989 r_glsl_permutation_t *r_glsl_permutation;
990 /// storage for permutations linked in the hash table
991 memexpandablearray_t r_glsl_permutationarray;
993 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
995 //unsigned int hashdepth = 0;
996 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
997 r_glsl_permutation_t *p;
998 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1000 if (p->mode == mode && p->permutation == permutation)
1002 //if (hashdepth > 10)
1003 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1008 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1010 p->permutation = permutation;
1011 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1012 r_glsl_permutationhash[mode][hashindex] = p;
1013 //if (hashdepth > 10)
1014 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1018 static char *R_ShaderStrCat(const char **strings)
1021 const char **p = strings;
1024 for (p = strings;(t = *p);p++)
1027 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1029 for (p = strings;(t = *p);p++)
1039 static char *R_ShaderStrCat(const char **strings);
1040 static void R_InitShaderModeInfo(void)
1043 shadermodeinfo_t *modeinfo;
1044 // we have a bunch of things to compute that weren't calculated at engine compile time - all filenames should have a crc of the builtin strings to prevent accidental overrides (any customization must be updated to match engine)
1045 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1047 for (i = 0; i < SHADERMODE_COUNT; i++)
1049 char filename[MAX_QPATH];
1050 modeinfo = &shadermodeinfo[language][i];
1051 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1052 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1053 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1054 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1059 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1062 // if the mode has no filename we have to return the builtin string
1063 if (builtinonly || !modeinfo->filename)
1064 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1065 // note that FS_LoadFile appends a 0 byte to make it a valid string
1066 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1069 if (printfromdisknotice)
1070 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1071 return shaderstring;
1073 // fall back to builtinstring
1074 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1077 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1082 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1084 char permutationname[256];
1085 int vertstrings_count = 0;
1086 int geomstrings_count = 0;
1087 int fragstrings_count = 0;
1088 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1089 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1090 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1097 permutationname[0] = 0;
1098 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1100 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1102 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1103 if(vid.support.glshaderversion >= 140)
1105 vertstrings_list[vertstrings_count++] = "#version 140\n";
1106 geomstrings_list[geomstrings_count++] = "#version 140\n";
1107 fragstrings_list[fragstrings_count++] = "#version 140\n";
1108 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1109 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1110 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1112 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1113 else if(vid.support.glshaderversion >= 130)
1115 vertstrings_list[vertstrings_count++] = "#version 130\n";
1116 geomstrings_list[geomstrings_count++] = "#version 130\n";
1117 fragstrings_list[fragstrings_count++] = "#version 130\n";
1118 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1119 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1120 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1122 // if we can do #version 120, we should (this adds the invariant keyword)
1123 else if(vid.support.glshaderversion >= 120)
1125 vertstrings_list[vertstrings_count++] = "#version 120\n";
1126 geomstrings_list[geomstrings_count++] = "#version 120\n";
1127 fragstrings_list[fragstrings_count++] = "#version 120\n";
1128 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1129 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1130 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1132 // GLES also adds several things from GLSL120
1133 switch(vid.renderpath)
1135 case RENDERPATH_GLES2:
1136 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1137 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1138 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1144 // the first pretext is which type of shader to compile as
1145 // (later these will all be bound together as a program object)
1146 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1147 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1148 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1150 // the second pretext is the mode (for example a light source)
1151 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1152 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1153 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1154 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1156 // now add all the permutation pretexts
1157 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1159 if (permutation & (1ll<<i))
1161 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1162 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1163 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1164 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1168 // keep line numbers correct
1169 vertstrings_list[vertstrings_count++] = "\n";
1170 geomstrings_list[geomstrings_count++] = "\n";
1171 fragstrings_list[fragstrings_count++] = "\n";
1176 R_CompileShader_AddStaticParms(mode, permutation);
1177 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178 vertstrings_count += shaderstaticparms_count;
1179 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180 geomstrings_count += shaderstaticparms_count;
1181 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182 fragstrings_count += shaderstaticparms_count;
1184 // now append the shader text itself
1185 vertstrings_list[vertstrings_count++] = sourcestring;
1186 geomstrings_list[geomstrings_count++] = sourcestring;
1187 fragstrings_list[fragstrings_count++] = sourcestring;
1189 // compile the shader program
1190 if (vertstrings_count + geomstrings_count + fragstrings_count)
1191 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1195 qglUseProgram(p->program);CHECKGLERROR
1196 // look up all the uniform variable names we care about, so we don't
1197 // have to look them up every time we set them
1202 GLint activeuniformindex = 0;
1203 GLint numactiveuniforms = 0;
1204 char uniformname[128];
1205 GLsizei uniformnamelength = 0;
1206 GLint uniformsize = 0;
1207 GLenum uniformtype = 0;
1208 memset(uniformname, 0, sizeof(uniformname));
1209 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1210 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1211 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1213 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1214 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1219 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1220 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1221 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1222 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1223 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1224 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1225 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1226 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1227 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1228 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1229 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1230 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1231 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1232 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1233 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1234 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1235 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1236 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1237 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1238 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1239 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1240 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1241 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1242 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1243 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1244 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1245 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1246 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1247 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1248 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1249 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1250 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1251 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1252 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1253 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1254 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1255 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1256 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1257 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1258 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1259 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1260 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1261 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1262 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1263 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1264 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1265 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1266 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1267 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1268 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1269 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1270 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1271 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1272 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1273 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1274 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1275 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1276 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1277 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1278 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1279 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1280 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1281 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1282 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1283 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1284 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1285 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1286 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1287 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1288 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1289 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1290 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1291 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1292 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1293 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1294 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1295 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1296 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1297 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1298 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1299 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1300 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1301 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1302 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1303 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1304 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1305 // initialize the samplers to refer to the texture units we use
1306 p->tex_Texture_First = -1;
1307 p->tex_Texture_Second = -1;
1308 p->tex_Texture_GammaRamps = -1;
1309 p->tex_Texture_Normal = -1;
1310 p->tex_Texture_Color = -1;
1311 p->tex_Texture_Gloss = -1;
1312 p->tex_Texture_Glow = -1;
1313 p->tex_Texture_SecondaryNormal = -1;
1314 p->tex_Texture_SecondaryColor = -1;
1315 p->tex_Texture_SecondaryGloss = -1;
1316 p->tex_Texture_SecondaryGlow = -1;
1317 p->tex_Texture_Pants = -1;
1318 p->tex_Texture_Shirt = -1;
1319 p->tex_Texture_FogHeightTexture = -1;
1320 p->tex_Texture_FogMask = -1;
1321 p->tex_Texture_Lightmap = -1;
1322 p->tex_Texture_Deluxemap = -1;
1323 p->tex_Texture_Attenuation = -1;
1324 p->tex_Texture_Cube = -1;
1325 p->tex_Texture_Refraction = -1;
1326 p->tex_Texture_Reflection = -1;
1327 p->tex_Texture_ShadowMap2D = -1;
1328 p->tex_Texture_CubeProjection = -1;
1329 p->tex_Texture_ScreenNormalMap = -1;
1330 p->tex_Texture_ScreenDiffuse = -1;
1331 p->tex_Texture_ScreenSpecular = -1;
1332 p->tex_Texture_ReflectMask = -1;
1333 p->tex_Texture_ReflectCube = -1;
1334 p->tex_Texture_BounceGrid = -1;
1335 // bind the texture samplers in use
1337 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1338 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1339 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1340 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1341 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1342 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1343 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1344 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1345 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1346 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1347 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1348 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1349 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1350 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1351 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1352 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1353 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1354 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1355 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1356 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1357 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1358 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1359 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1360 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1361 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1362 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1363 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1364 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1365 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1366 // get the uniform block indices so we can bind them
1367 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1368 if (vid.support.arb_uniform_buffer_object)
1369 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1372 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1373 // clear the uniform block bindings
1374 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1375 // bind the uniform blocks in use
1377 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1378 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1380 // we're done compiling and setting up the shader, at least until it is used
1382 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1385 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1389 Mem_Free(sourcestring);
1392 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1394 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1395 if (r_glsl_permutation != perm)
1397 r_glsl_permutation = perm;
1398 if (!r_glsl_permutation->program)
1400 if (!r_glsl_permutation->compiled)
1402 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1403 R_GLSL_CompilePermutation(perm, mode, permutation);
1405 if (!r_glsl_permutation->program)
1407 // remove features until we find a valid permutation
1409 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1411 // reduce i more quickly whenever it would not remove any bits
1412 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1413 if (!(permutation & j))
1416 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1417 if (!r_glsl_permutation->compiled)
1418 R_GLSL_CompilePermutation(perm, mode, permutation);
1419 if (r_glsl_permutation->program)
1422 if (i >= SHADERPERMUTATION_COUNT)
1424 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1425 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1426 qglUseProgram(0);CHECKGLERROR
1427 return; // no bit left to clear, entire mode is broken
1432 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1434 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1435 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1436 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1444 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1445 extern D3DCAPS9 vid_d3d9caps;
1448 struct r_hlsl_permutation_s;
1449 typedef struct r_hlsl_permutation_s
1451 /// hash lookup data
1452 struct r_hlsl_permutation_s *hashnext;
1454 dpuint64 permutation;
1456 /// indicates if we have tried compiling this permutation already
1458 /// NULL if compilation failed
1459 IDirect3DVertexShader9 *vertexshader;
1460 IDirect3DPixelShader9 *pixelshader;
1462 r_hlsl_permutation_t;
1464 typedef enum D3DVSREGISTER_e
1466 D3DVSREGISTER_TexMatrix = 0, // float4x4
1467 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1468 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1469 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1470 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1471 D3DVSREGISTER_ModelToLight = 20, // float4x4
1472 D3DVSREGISTER_EyePosition = 24,
1473 D3DVSREGISTER_FogPlane = 25,
1474 D3DVSREGISTER_LightDir = 26,
1475 D3DVSREGISTER_LightPosition = 27,
1479 typedef enum D3DPSREGISTER_e
1481 D3DPSREGISTER_Alpha = 0,
1482 D3DPSREGISTER_BloomBlur_Parameters = 1,
1483 D3DPSREGISTER_ClientTime = 2,
1484 D3DPSREGISTER_Color_Ambient = 3,
1485 D3DPSREGISTER_Color_Diffuse = 4,
1486 D3DPSREGISTER_Color_Specular = 5,
1487 D3DPSREGISTER_Color_Glow = 6,
1488 D3DPSREGISTER_Color_Pants = 7,
1489 D3DPSREGISTER_Color_Shirt = 8,
1490 D3DPSREGISTER_DeferredColor_Ambient = 9,
1491 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1492 D3DPSREGISTER_DeferredColor_Specular = 11,
1493 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1494 D3DPSREGISTER_DeferredMod_Specular = 13,
1495 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1496 D3DPSREGISTER_EyePosition = 15, // unused
1497 D3DPSREGISTER_FogColor = 16,
1498 D3DPSREGISTER_FogHeightFade = 17,
1499 D3DPSREGISTER_FogPlane = 18,
1500 D3DPSREGISTER_FogPlaneViewDist = 19,
1501 D3DPSREGISTER_FogRangeRecip = 20,
1502 D3DPSREGISTER_LightColor = 21,
1503 D3DPSREGISTER_LightDir = 22, // unused
1504 D3DPSREGISTER_LightPosition = 23,
1505 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1506 D3DPSREGISTER_PixelSize = 25,
1507 D3DPSREGISTER_ReflectColor = 26,
1508 D3DPSREGISTER_ReflectFactor = 27,
1509 D3DPSREGISTER_ReflectOffset = 28,
1510 D3DPSREGISTER_RefractColor = 29,
1511 D3DPSREGISTER_Saturation = 30,
1512 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1513 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1514 D3DPSREGISTER_ScreenToDepth = 33,
1515 D3DPSREGISTER_ShadowMap_Parameters = 34,
1516 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1517 D3DPSREGISTER_SpecularPower = 36,
1518 D3DPSREGISTER_UserVec1 = 37,
1519 D3DPSREGISTER_UserVec2 = 38,
1520 D3DPSREGISTER_UserVec3 = 39,
1521 D3DPSREGISTER_UserVec4 = 40,
1522 D3DPSREGISTER_ViewTintColor = 41,
1523 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1524 D3DPSREGISTER_BloomColorSubtract = 43,
1525 D3DPSREGISTER_ViewToLight = 44, // float4x4
1526 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1527 D3DPSREGISTER_NormalmapScrollBlend = 52,
1528 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1529 D3DPSREGISTER_OffsetMapping_Bias = 54,
1534 /// information about each possible shader permutation
1535 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1536 /// currently selected permutation
1537 r_hlsl_permutation_t *r_hlsl_permutation;
1538 /// storage for permutations linked in the hash table
1539 memexpandablearray_t r_hlsl_permutationarray;
1541 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1543 //unsigned int hashdepth = 0;
1544 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1545 r_hlsl_permutation_t *p;
1546 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1548 if (p->mode == mode && p->permutation == permutation)
1550 //if (hashdepth > 10)
1551 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1556 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1558 p->permutation = permutation;
1559 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1560 r_hlsl_permutationhash[mode][hashindex] = p;
1561 //if (hashdepth > 10)
1562 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1567 //#include <d3dx9shader.h>
1568 //#include <d3dx9mesh.h>
1570 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1572 DWORD *vsbin = NULL;
1573 DWORD *psbin = NULL;
1574 fs_offset_t vsbinsize;
1575 fs_offset_t psbinsize;
1576 // IDirect3DVertexShader9 *vs = NULL;
1577 // IDirect3DPixelShader9 *ps = NULL;
1578 ID3DXBuffer *vslog = NULL;
1579 ID3DXBuffer *vsbuffer = NULL;
1580 ID3DXConstantTable *vsconstanttable = NULL;
1581 ID3DXBuffer *pslog = NULL;
1582 ID3DXBuffer *psbuffer = NULL;
1583 ID3DXConstantTable *psconstanttable = NULL;
1586 char temp[MAX_INPUTLINE];
1587 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1589 qboolean debugshader = gl_paranoid.integer != 0;
1590 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1591 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1594 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1595 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1597 if ((!vsbin && vertstring) || (!psbin && fragstring))
1599 const char* dllnames_d3dx9 [] =
1623 dllhandle_t d3dx9_dll = NULL;
1624 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1626 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1627 dllfunction_t d3dx9_dllfuncs[] =
1629 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1630 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1631 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1634 // 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...
1635 #ifndef ID3DXBuffer_GetBufferPointer
1636 #if !defined(__cplusplus) || defined(CINTERFACE)
1637 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1638 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1639 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1641 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1642 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1643 #define ID3DXBuffer_Release(p) (p)->Release()
1646 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1648 DWORD shaderflags = 0;
1650 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1651 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1652 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1653 if (vertstring && vertstring[0])
1657 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1658 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1661 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1664 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1665 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1666 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1667 ID3DXBuffer_Release(vsbuffer);
1671 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1672 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1673 ID3DXBuffer_Release(vslog);
1676 if (fragstring && fragstring[0])
1680 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1681 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1684 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1687 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1688 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1689 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1690 ID3DXBuffer_Release(psbuffer);
1694 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1695 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1696 ID3DXBuffer_Release(pslog);
1699 Sys_UnloadLibrary(&d3dx9_dll);
1702 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1706 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1707 if (FAILED(vsresult))
1708 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1709 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1710 if (FAILED(psresult))
1711 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1713 // free the shader data
1714 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1715 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1718 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1721 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1722 int vertstring_length = 0;
1723 int geomstring_length = 0;
1724 int fragstring_length = 0;
1727 char *vertstring, *geomstring, *fragstring;
1728 char permutationname[256];
1729 char cachename[256];
1730 int vertstrings_count = 0;
1731 int geomstrings_count = 0;
1732 int fragstrings_count = 0;
1733 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1734 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1735 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740 p->vertexshader = NULL;
1741 p->pixelshader = NULL;
1743 permutationname[0] = 0;
1745 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1747 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1748 strlcat(cachename, "hlsl/", sizeof(cachename));
1750 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1751 vertstrings_count = 0;
1752 geomstrings_count = 0;
1753 fragstrings_count = 0;
1754 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1755 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1756 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1758 // the first pretext is which type of shader to compile as
1759 // (later these will all be bound together as a program object)
1760 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1761 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1762 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1764 // the second pretext is the mode (for example a light source)
1765 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1766 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1767 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1768 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1769 strlcat(cachename, modeinfo->name, sizeof(cachename));
1771 // now add all the permutation pretexts
1772 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1774 if (permutation & (1ll<<i))
1776 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1777 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1778 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1779 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1780 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1784 // keep line numbers correct
1785 vertstrings_list[vertstrings_count++] = "\n";
1786 geomstrings_list[geomstrings_count++] = "\n";
1787 fragstrings_list[fragstrings_count++] = "\n";
1792 R_CompileShader_AddStaticParms(mode, permutation);
1793 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794 vertstrings_count += shaderstaticparms_count;
1795 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796 geomstrings_count += shaderstaticparms_count;
1797 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798 fragstrings_count += shaderstaticparms_count;
1800 // replace spaces in the cachename with _ characters
1801 for (i = 0;cachename[i];i++)
1802 if (cachename[i] == ' ')
1805 // now append the shader text itself
1806 vertstrings_list[vertstrings_count++] = sourcestring;
1807 geomstrings_list[geomstrings_count++] = sourcestring;
1808 fragstrings_list[fragstrings_count++] = sourcestring;
1810 vertstring_length = 0;
1811 for (i = 0;i < vertstrings_count;i++)
1812 vertstring_length += (int)strlen(vertstrings_list[i]);
1813 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1814 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1815 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1817 geomstring_length = 0;
1818 for (i = 0;i < geomstrings_count;i++)
1819 geomstring_length += (int)strlen(geomstrings_list[i]);
1820 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1821 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1822 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1824 fragstring_length = 0;
1825 for (i = 0;i < fragstrings_count;i++)
1826 fragstring_length += (int)strlen(fragstrings_list[i]);
1827 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1828 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1829 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1831 // try to load the cached shader, or generate one
1832 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1834 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1835 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1837 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1841 Mem_Free(vertstring);
1843 Mem_Free(geomstring);
1845 Mem_Free(fragstring);
1847 Mem_Free(sourcestring);
1850 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1851 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1852 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);}
1853 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);}
1854 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);}
1855 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);}
1857 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1858 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1859 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);}
1860 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);}
1861 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);}
1862 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);}
1864 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1866 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1867 if (r_hlsl_permutation != perm)
1869 r_hlsl_permutation = perm;
1870 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1872 if (!r_hlsl_permutation->compiled)
1873 R_HLSL_CompilePermutation(perm, mode, permutation);
1874 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1876 // remove features until we find a valid permutation
1878 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880 // reduce i more quickly whenever it would not remove any bits
1881 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1882 if (!(permutation & j))
1885 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1886 if (!r_hlsl_permutation->compiled)
1887 R_HLSL_CompilePermutation(perm, mode, permutation);
1888 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1891 if (i >= SHADERPERMUTATION_COUNT)
1893 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1894 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1895 return; // no bit left to clear, entire mode is broken
1899 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1900 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1902 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1903 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1904 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1908 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1910 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1911 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1912 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1913 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1916 void R_GLSL_Restart_f(void)
1918 unsigned int i, limit;
1919 switch(vid.renderpath)
1921 case RENDERPATH_D3D9:
1924 r_hlsl_permutation_t *p;
1925 r_hlsl_permutation = NULL;
1926 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1927 for (i = 0;i < limit;i++)
1929 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1931 if (p->vertexshader)
1932 IDirect3DVertexShader9_Release(p->vertexshader);
1934 IDirect3DPixelShader9_Release(p->pixelshader);
1935 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1938 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1942 case RENDERPATH_D3D10:
1943 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945 case RENDERPATH_D3D11:
1946 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948 case RENDERPATH_GL20:
1949 case RENDERPATH_GLES2:
1951 r_glsl_permutation_t *p;
1952 r_glsl_permutation = NULL;
1953 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1954 for (i = 0;i < limit;i++)
1956 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1958 GL_Backend_FreeProgram(p->program);
1959 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1962 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1965 case RENDERPATH_GL11:
1966 case RENDERPATH_GL13:
1967 case RENDERPATH_GLES1:
1969 case RENDERPATH_SOFT:
1974 static void R_GLSL_DumpShader_f(void)
1976 int i, language, mode, dupe;
1978 shadermodeinfo_t *modeinfo;
1981 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1983 modeinfo = shadermodeinfo[language];
1984 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1986 // don't dump the same file multiple times (most or all shaders come from the same file)
1987 for (dupe = mode - 1;dupe >= 0;dupe--)
1988 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1992 text = modeinfo[mode].builtinstring;
1995 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1998 FS_Print(file, "/* The engine may define the following macros:\n");
1999 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2000 for (i = 0;i < SHADERMODE_COUNT;i++)
2001 FS_Print(file, modeinfo[i].pretext);
2002 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2003 FS_Print(file, shaderpermutationinfo[i].pretext);
2004 FS_Print(file, "*/\n");
2005 FS_Print(file, text);
2007 Con_Printf("%s written\n", modeinfo[mode].filename);
2010 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2015 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2017 dpuint64 permutation = 0;
2018 if (r_trippy.integer && !notrippy)
2019 permutation |= SHADERPERMUTATION_TRIPPY;
2020 permutation |= SHADERPERMUTATION_VIEWTINT;
2022 permutation |= SHADERPERMUTATION_DIFFUSE;
2024 permutation |= SHADERPERMUTATION_SPECULAR;
2025 if (texturemode == GL_MODULATE)
2026 permutation |= SHADERPERMUTATION_COLORMAPPING;
2027 else if (texturemode == GL_ADD)
2028 permutation |= SHADERPERMUTATION_GLOW;
2029 else if (texturemode == GL_DECAL)
2030 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2031 if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2032 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2033 if (suppresstexalpha)
2034 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2036 texturemode = GL_MODULATE;
2037 if (vid.allowalphatocoverage)
2038 GL_AlphaToCoverage(false);
2039 switch (vid.renderpath)
2041 case RENDERPATH_D3D9:
2043 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2044 R_Mesh_TexBind(GL20TU_FIRST , first );
2045 R_Mesh_TexBind(GL20TU_SECOND, second);
2046 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2047 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2050 case RENDERPATH_D3D10:
2051 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2053 case RENDERPATH_D3D11:
2054 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2056 case RENDERPATH_GL20:
2057 case RENDERPATH_GLES2:
2058 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2059 if (r_glsl_permutation->tex_Texture_First >= 0)
2060 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2061 if (r_glsl_permutation->tex_Texture_Second >= 0)
2062 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2063 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2064 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2066 case RENDERPATH_GL13:
2067 case RENDERPATH_GLES1:
2068 R_Mesh_TexBind(0, first );
2069 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2070 R_Mesh_TexMatrix(0, NULL);
2071 R_Mesh_TexBind(1, second);
2074 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2075 R_Mesh_TexMatrix(1, NULL);
2078 case RENDERPATH_GL11:
2079 R_Mesh_TexBind(0, first );
2080 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2081 R_Mesh_TexMatrix(0, NULL);
2083 case RENDERPATH_SOFT:
2084 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2085 R_Mesh_TexBind(GL20TU_FIRST , first );
2086 R_Mesh_TexBind(GL20TU_SECOND, second);
2091 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2093 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2096 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2098 dpuint64 permutation = 0;
2099 if (r_trippy.integer && !notrippy)
2100 permutation |= SHADERPERMUTATION_TRIPPY;
2102 permutation |= SHADERPERMUTATION_DEPTHRGB;
2104 permutation |= SHADERPERMUTATION_SKELETAL;
2106 if (vid.allowalphatocoverage)
2107 GL_AlphaToCoverage(false);
2108 switch (vid.renderpath)
2110 case RENDERPATH_D3D9:
2112 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 case RENDERPATH_D3D10:
2116 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2118 case RENDERPATH_D3D11:
2119 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2121 case RENDERPATH_GL20:
2122 case RENDERPATH_GLES2:
2123 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2124 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2125 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);
2128 case RENDERPATH_GL13:
2129 case RENDERPATH_GLES1:
2130 R_Mesh_TexBind(0, 0);
2131 R_Mesh_TexBind(1, 0);
2133 case RENDERPATH_GL11:
2134 R_Mesh_TexBind(0, 0);
2136 case RENDERPATH_SOFT:
2137 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2142 #define BLENDFUNC_ALLOWS_COLORMOD 1
2143 #define BLENDFUNC_ALLOWS_FOG 2
2144 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2145 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2146 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2147 static int R_BlendFuncFlags(int src, int dst)
2151 // a blendfunc allows colormod if:
2152 // a) it can never keep the destination pixel invariant, or
2153 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2154 // this is to prevent unintended side effects from colormod
2156 // a blendfunc allows fog if:
2157 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2158 // this is to prevent unintended side effects from fog
2160 // these checks are the output of fogeval.pl
2162 r |= BLENDFUNC_ALLOWS_COLORMOD;
2163 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2164 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2165 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2167 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2171 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2172 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2173 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2174 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2176 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2181 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2183 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2188 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2190 // select a permutation of the lighting shader appropriate to this
2191 // combination of texture, entity, light source, and fogging, only use the
2192 // minimum features necessary to avoid wasting rendering time in the
2193 // fragment shader on features that are not being used
2194 dpuint64 permutation = 0;
2195 unsigned int mode = 0;
2197 texture_t *t = rsurface.texture;
2199 matrix4x4_t tempmatrix;
2200 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2201 if (r_trippy.integer && !notrippy)
2202 permutation |= SHADERPERMUTATION_TRIPPY;
2203 if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2204 permutation |= SHADERPERMUTATION_ALPHAKILL;
2205 if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2206 permutation |= SHADERPERMUTATION_OCCLUDE;
2207 if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2208 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2209 if (rsurfacepass == RSURFPASS_BACKGROUND)
2211 // distorted background
2212 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2214 mode = SHADERMODE_WATER;
2215 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2216 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2217 if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2219 // this is the right thing to do for wateralpha
2220 GL_BlendFunc(GL_ONE, GL_ZERO);
2221 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2225 // this is the right thing to do for entity alpha
2226 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2227 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2230 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2232 mode = SHADERMODE_REFRACTION;
2233 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2234 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2235 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2236 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240 mode = SHADERMODE_GENERIC;
2241 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2242 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2245 if (vid.allowalphatocoverage)
2246 GL_AlphaToCoverage(false);
2248 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2250 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2252 switch(t->offsetmapping)
2254 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2255 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2256 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257 case OFFSETMAPPING_OFF: break;
2260 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2261 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2262 // normalmap (deferred prepass), may use alpha test on diffuse
2263 mode = SHADERMODE_DEFERREDGEOMETRY;
2264 GL_BlendFunc(GL_ONE, GL_ZERO);
2265 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2266 if (vid.allowalphatocoverage)
2267 GL_AlphaToCoverage(false);
2269 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2271 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2273 switch(t->offsetmapping)
2275 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2276 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2277 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2278 case OFFSETMAPPING_OFF: break;
2281 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2282 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2283 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2284 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2286 mode = SHADERMODE_LIGHTSOURCE;
2287 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2288 permutation |= SHADERPERMUTATION_CUBEFILTER;
2289 if (VectorLength2(rtlightdiffuse) > 0)
2290 permutation |= SHADERPERMUTATION_DIFFUSE;
2291 if (VectorLength2(rtlightspecular) > 0)
2292 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2293 if (r_refdef.fogenabled)
2294 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2295 if (t->colormapping)
2296 permutation |= SHADERPERMUTATION_COLORMAPPING;
2297 if (r_shadow_usingshadowmap2d)
2299 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2300 if(r_shadow_shadowmapvsdct)
2301 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2303 if (r_shadow_shadowmap2ddepthbuffer)
2304 permutation |= SHADERPERMUTATION_DEPTHRGB;
2306 if (t->reflectmasktexture)
2307 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2308 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2309 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2310 if (vid.allowalphatocoverage)
2311 GL_AlphaToCoverage(false);
2313 else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2315 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2317 switch(t->offsetmapping)
2319 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2320 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2321 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322 case OFFSETMAPPING_OFF: break;
2325 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2326 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2327 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2328 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2329 // directional model lighting
2330 mode = SHADERMODE_LIGHTDIRECTION;
2331 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2332 permutation |= SHADERPERMUTATION_GLOW;
2333 if (VectorLength2(t->render_modellight_diffuse))
2334 permutation |= SHADERPERMUTATION_DIFFUSE;
2335 if (VectorLength2(t->render_modellight_specular) > 0)
2336 permutation |= SHADERPERMUTATION_SPECULAR;
2337 if (r_refdef.fogenabled)
2338 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2339 if (t->colormapping)
2340 permutation |= SHADERPERMUTATION_COLORMAPPING;
2341 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2343 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2344 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2346 if (r_shadow_shadowmap2ddepthbuffer)
2347 permutation |= SHADERPERMUTATION_DEPTHRGB;
2349 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2350 permutation |= SHADERPERMUTATION_REFLECTION;
2351 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2352 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2353 if (t->reflectmasktexture)
2354 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2355 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2357 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2358 if (r_shadow_bouncegrid_state.directional)
2359 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2361 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2362 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2363 // when using alphatocoverage, we don't need alphakill
2364 if (vid.allowalphatocoverage)
2366 if (r_transparent_alphatocoverage.integer)
2368 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2369 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2372 GL_AlphaToCoverage(false);
2377 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2379 switch(t->offsetmapping)
2381 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2382 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2383 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384 case OFFSETMAPPING_OFF: break;
2387 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2388 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2389 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2390 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2392 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2393 permutation |= SHADERPERMUTATION_GLOW;
2394 if (r_refdef.fogenabled)
2395 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2396 if (t->colormapping)
2397 permutation |= SHADERPERMUTATION_COLORMAPPING;
2398 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2400 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2401 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2403 if (r_shadow_shadowmap2ddepthbuffer)
2404 permutation |= SHADERPERMUTATION_DEPTHRGB;
2406 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2407 permutation |= SHADERPERMUTATION_REFLECTION;
2408 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2409 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2410 if (t->reflectmasktexture)
2411 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2412 if (FAKELIGHT_ENABLED)
2414 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2415 mode = SHADERMODE_FAKELIGHT;
2416 permutation |= SHADERPERMUTATION_DIFFUSE;
2417 if (VectorLength2(t->render_lightmap_specular) > 0)
2418 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2420 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2422 // deluxemapping (light direction texture)
2423 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2424 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2426 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2427 permutation |= SHADERPERMUTATION_DIFFUSE;
2428 if (VectorLength2(t->render_lightmap_specular) > 0)
2429 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2431 else if (r_glsl_deluxemapping.integer >= 2)
2433 // fake deluxemapping (uniform light direction in tangentspace)
2434 if (rsurface.uselightmaptexture)
2435 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2437 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2438 permutation |= SHADERPERMUTATION_DIFFUSE;
2439 if (VectorLength2(t->render_lightmap_specular) > 0)
2440 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2442 else if (rsurface.uselightmaptexture)
2444 // ordinary lightmapping (q1bsp, q3bsp)
2445 mode = SHADERMODE_LIGHTMAP;
2449 // ordinary vertex coloring (q3bsp)
2450 mode = SHADERMODE_VERTEXCOLOR;
2452 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2454 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2455 if (r_shadow_bouncegrid_state.directional)
2456 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2458 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2459 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2460 // when using alphatocoverage, we don't need alphakill
2461 if (vid.allowalphatocoverage)
2463 if (r_transparent_alphatocoverage.integer)
2465 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2466 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2469 GL_AlphaToCoverage(false);
2472 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2473 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2474 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2475 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2476 switch(vid.renderpath)
2478 case RENDERPATH_D3D9:
2480 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);
2481 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2482 R_SetupShader_SetPermutationHLSL(mode, permutation);
2483 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2484 if (mode == SHADERMODE_LIGHTSOURCE)
2486 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2487 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2491 if (mode == SHADERMODE_LIGHTDIRECTION)
2493 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2496 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2497 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2498 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2499 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2500 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2502 if (mode == SHADERMODE_LIGHTSOURCE)
2504 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2505 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2506 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2508 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2510 // additive passes are only darkened by fog, not tinted
2511 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2512 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2516 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2517 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2518 if (mode == SHADERMODE_FLATCOLOR)
2520 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2522 else if (mode == SHADERMODE_LIGHTDIRECTION)
2524 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2526 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2527 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2528 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2532 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2533 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2534 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2536 // additive passes are only darkened by fog, not tinted
2537 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2538 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2541 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2542 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2543 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2544 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2545 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2546 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2547 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2548 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2549 if (mode == SHADERMODE_WATER)
2550 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2552 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2554 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2555 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2559 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2560 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2563 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2564 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2565 if (t->pantstexture)
2566 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2568 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2569 if (t->shirttexture)
2570 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2572 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2573 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2574 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2575 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2576 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2577 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2578 r_glsl_offsetmapping_scale.value*t->offsetscale,
2579 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2580 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2581 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2583 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2584 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2585 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2586 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2588 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2589 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2590 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2591 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2592 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2593 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2594 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2595 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2596 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2597 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2598 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2599 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2600 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2601 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2602 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2603 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2604 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2605 if (rsurfacepass == RSURFPASS_BACKGROUND)
2607 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2608 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2609 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2613 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2615 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2616 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2617 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2618 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2620 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2621 if (rsurface.rtlight)
2623 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2624 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2629 case RENDERPATH_D3D10:
2630 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2632 case RENDERPATH_D3D11:
2633 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2635 case RENDERPATH_GL20:
2636 case RENDERPATH_GLES2:
2637 if (!vid.useinterleavedarrays)
2639 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);
2640 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2641 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2642 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2643 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2644 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2645 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2646 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2647 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2648 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2649 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2653 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);
2654 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2656 // this has to be after RSurf_PrepareVerticesForBatch
2657 if (rsurface.batchskeletaltransform3x4buffer)
2658 permutation |= SHADERPERMUTATION_SKELETAL;
2659 R_SetupShader_SetPermutationGLSL(mode, permutation);
2660 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2661 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);
2663 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2664 if (mode == SHADERMODE_LIGHTSOURCE)
2666 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2667 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2668 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2669 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2670 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2671 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2673 // additive passes are only darkened by fog, not tinted
2674 if (r_glsl_permutation->loc_FogColor >= 0)
2675 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2676 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2680 if (mode == SHADERMODE_FLATCOLOR)
2682 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2684 else if (mode == SHADERMODE_LIGHTDIRECTION)
2686 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2687 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2688 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2689 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2690 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2691 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2692 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2696 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2697 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2698 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2699 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2700 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2702 // additive passes are only darkened by fog, not tinted
2703 if (r_glsl_permutation->loc_FogColor >= 0)
2705 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2706 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2708 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2710 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2711 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]);
2712 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]);
2713 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2714 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2715 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2716 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2717 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2718 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2720 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2721 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2722 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2723 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2725 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2726 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2730 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2731 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2734 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2735 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2736 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2737 if (r_glsl_permutation->loc_Color_Pants >= 0)
2739 if (t->pantstexture)
2740 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2742 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2744 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2746 if (t->shirttexture)
2747 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2749 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2751 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]);
2752 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2753 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2754 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2755 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2756 r_glsl_offsetmapping_scale.value*t->offsetscale,
2757 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2758 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2759 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2761 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);
2762 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2763 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]);
2764 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2765 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2766 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2768 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2769 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2770 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2771 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , t->nmaptexture );
2772 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , t->basetexture );
2773 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , t->glosstexture );
2774 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , t->glowtexture );
2775 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , t->backgroundnmaptexture );
2776 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , t->backgroundbasetexture );
2777 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , t->backgroundglosstexture );
2778 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , t->backgroundglowtexture );
2779 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , t->pantstexture );
2780 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , t->shirttexture );
2781 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , t->reflectmasktexture );
2782 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2783 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2784 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2785 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2786 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2787 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2788 if (rsurfacepass == RSURFPASS_BACKGROUND)
2790 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2791 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2792 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2796 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2798 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2799 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2800 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2801 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2803 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2804 if (rsurface.rtlight)
2806 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2807 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2810 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2813 case RENDERPATH_GL11:
2814 case RENDERPATH_GL13:
2815 case RENDERPATH_GLES1:
2817 case RENDERPATH_SOFT:
2818 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);
2819 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2820 R_SetupShader_SetPermutationSoft(mode, permutation);
2821 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2822 if (mode == SHADERMODE_LIGHTSOURCE)
2824 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2825 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2826 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2828 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2829 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2831 // additive passes are only darkened by fog, not tinted
2832 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2833 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2837 if (mode == SHADERMODE_FLATCOLOR)
2839 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2841 else if (mode == SHADERMODE_LIGHTDIRECTION)
2843 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2844 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2846 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2847 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2852 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2856 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2857 // additive passes are only darkened by fog, not tinted
2858 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2861 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2862 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2863 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]);
2864 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]);
2865 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2866 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2867 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2868 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2869 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2870 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2872 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2873 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2874 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2875 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2877 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2878 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2882 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2883 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2887 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2888 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2889 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2891 if (t->pantstexture)
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2894 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2896 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2898 if (t->shirttexture)
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2901 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2903 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2905 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2906 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2907 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2908 r_glsl_offsetmapping_scale.value*t->offsetscale,
2909 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2910 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2913 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2914 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2915 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2916 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2918 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2919 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2920 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2921 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2922 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2923 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2924 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2925 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2926 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2927 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2928 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2929 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2930 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2931 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2932 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2933 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2934 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2935 if (rsurfacepass == RSURFPASS_BACKGROUND)
2937 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2938 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2939 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2943 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2945 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2946 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2947 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2948 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2950 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2951 if (rsurface.rtlight)
2953 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2954 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2961 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2963 // select a permutation of the lighting shader appropriate to this
2964 // combination of texture, entity, light source, and fogging, only use the
2965 // minimum features necessary to avoid wasting rendering time in the
2966 // fragment shader on features that are not being used
2967 dpuint64 permutation = 0;
2968 unsigned int mode = 0;
2969 const float *lightcolorbase = rtlight->currentcolor;
2970 float ambientscale = rtlight->ambientscale;
2971 float diffusescale = rtlight->diffusescale;
2972 float specularscale = rtlight->specularscale;
2973 // this is the location of the light in view space
2974 vec3_t viewlightorigin;
2975 // this transforms from view space (camera) to light space (cubemap)
2976 matrix4x4_t viewtolight;
2977 matrix4x4_t lighttoview;
2978 float viewtolight16f[16];
2980 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2981 if (rtlight->currentcubemap != r_texture_whitecube)
2982 permutation |= SHADERPERMUTATION_CUBEFILTER;
2983 if (diffusescale > 0)
2984 permutation |= SHADERPERMUTATION_DIFFUSE;
2985 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2986 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2987 if (r_shadow_usingshadowmap2d)
2989 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2990 if (r_shadow_shadowmapvsdct)
2991 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2993 if (r_shadow_shadowmap2ddepthbuffer)
2994 permutation |= SHADERPERMUTATION_DEPTHRGB;
2996 if (vid.allowalphatocoverage)
2997 GL_AlphaToCoverage(false);
2998 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2999 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3000 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3001 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3002 switch(vid.renderpath)
3004 case RENDERPATH_D3D9:
3006 R_SetupShader_SetPermutationHLSL(mode, permutation);
3007 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3008 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3009 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3010 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3011 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3012 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3013 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3014 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);
3015 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3016 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3018 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3019 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3020 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3021 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3022 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3025 case RENDERPATH_D3D10:
3026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3028 case RENDERPATH_D3D11:
3029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031 case RENDERPATH_GL20:
3032 case RENDERPATH_GLES2:
3033 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3036 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3037 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3038 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3039 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3040 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3041 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);
3042 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]);
3043 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3045 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3046 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3047 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3048 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3049 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3051 case RENDERPATH_GL11:
3052 case RENDERPATH_GL13:
3053 case RENDERPATH_GLES1:
3055 case RENDERPATH_SOFT:
3056 R_SetupShader_SetPermutationGLSL(mode, permutation);
3057 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3058 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3059 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3060 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3061 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3062 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3063 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3064 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);
3065 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3066 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3068 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3069 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3070 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3071 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3072 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3077 #define SKINFRAME_HASH 1024
3081 unsigned int loadsequence; // incremented each level change
3082 memexpandablearray_t array;
3083 skinframe_t *hash[SKINFRAME_HASH];
3086 r_skinframe_t r_skinframe;
3088 void R_SkinFrame_PrepareForPurge(void)
3090 r_skinframe.loadsequence++;
3091 // wrap it without hitting zero
3092 if (r_skinframe.loadsequence >= 200)
3093 r_skinframe.loadsequence = 1;
3096 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3100 // mark the skinframe as used for the purging code
3101 skinframe->loadsequence = r_skinframe.loadsequence;
3104 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3106 if (s->merged == s->base)
3108 R_PurgeTexture(s->stain); s->stain = NULL;
3109 R_PurgeTexture(s->merged); s->merged = NULL;
3110 R_PurgeTexture(s->base); s->base = NULL;
3111 R_PurgeTexture(s->pants); s->pants = NULL;
3112 R_PurgeTexture(s->shirt); s->shirt = NULL;
3113 R_PurgeTexture(s->nmap); s->nmap = NULL;
3114 R_PurgeTexture(s->gloss); s->gloss = NULL;
3115 R_PurgeTexture(s->glow); s->glow = NULL;
3116 R_PurgeTexture(s->fog); s->fog = NULL;
3117 R_PurgeTexture(s->reflect); s->reflect = NULL;
3118 s->loadsequence = 0;
3121 void R_SkinFrame_Purge(void)
3125 for (i = 0;i < SKINFRAME_HASH;i++)
3127 for (s = r_skinframe.hash[i];s;s = s->next)
3129 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3130 R_SkinFrame_PurgeSkinFrame(s);
3135 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3137 char basename[MAX_QPATH];
3139 Image_StripImageExtension(name, basename, sizeof(basename));
3141 if( last == NULL ) {
3143 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3144 item = r_skinframe.hash[hashindex];
3149 // linearly search through the hash bucket
3150 for( ; item ; item = item->next ) {
3151 if( !strcmp( item->basename, basename ) ) {
3158 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3162 char basename[MAX_QPATH];
3164 Image_StripImageExtension(name, basename, sizeof(basename));
3166 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3168 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3175 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3176 memset(item, 0, sizeof(*item));
3177 strlcpy(item->basename, basename, sizeof(item->basename));
3178 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3179 item->comparewidth = comparewidth;
3180 item->compareheight = compareheight;
3181 item->comparecrc = comparecrc;
3182 item->next = r_skinframe.hash[hashindex];
3183 r_skinframe.hash[hashindex] = item;
3185 else if (textureflags & TEXF_FORCE_RELOAD)
3189 R_SkinFrame_PurgeSkinFrame(item);
3192 R_SkinFrame_MarkUsed(item);
3196 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3198 unsigned long long avgcolor[5], wsum; \
3206 for(pix = 0; pix < cnt; ++pix) \
3209 for(comp = 0; comp < 3; ++comp) \
3211 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3214 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3216 for(comp = 0; comp < 3; ++comp) \
3217 avgcolor[comp] += getpixel * w; \
3220 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3221 avgcolor[4] += getpixel; \
3223 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3225 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3226 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3227 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3228 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3231 extern cvar_t gl_picmip;
3232 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3235 unsigned char *pixels;
3236 unsigned char *bumppixels;
3237 unsigned char *basepixels = NULL;
3238 int basepixels_width = 0;
3239 int basepixels_height = 0;
3240 skinframe_t *skinframe;
3241 rtexture_t *ddsbase = NULL;
3242 qboolean ddshasalpha = false;
3243 float ddsavgcolor[4];
3244 char basename[MAX_QPATH];
3245 int miplevel = R_PicmipForFlags(textureflags);
3246 int savemiplevel = miplevel;
3250 if (cls.state == ca_dedicated)
3253 // return an existing skinframe if already loaded
3254 // if loading of the first image fails, don't make a new skinframe as it
3255 // would cause all future lookups of this to be missing
3256 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3257 if (skinframe && skinframe->base)
3260 Image_StripImageExtension(name, basename, sizeof(basename));
3262 // check for DDS texture file first
3263 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3265 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3266 if (basepixels == NULL && fallbacknotexture)
3267 basepixels = Image_GenerateNoTexture();
3268 if (basepixels == NULL)
3272 // FIXME handle miplevel
3274 if (developer_loading.integer)
3275 Con_Printf("loading skin \"%s\"\n", name);
3277 // we've got some pixels to store, so really allocate this new texture now
3279 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3280 textureflags &= ~TEXF_FORCE_RELOAD;
3281 skinframe->stain = NULL;
3282 skinframe->merged = NULL;
3283 skinframe->base = NULL;
3284 skinframe->pants = NULL;
3285 skinframe->shirt = NULL;
3286 skinframe->nmap = NULL;
3287 skinframe->gloss = NULL;
3288 skinframe->glow = NULL;
3289 skinframe->fog = NULL;
3290 skinframe->reflect = NULL;
3291 skinframe->hasalpha = false;
3292 // we could store the q2animname here too
3296 skinframe->base = ddsbase;
3297 skinframe->hasalpha = ddshasalpha;
3298 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3299 if (r_loadfog && skinframe->hasalpha)
3300 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);
3301 //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]);
3305 basepixels_width = image_width;
3306 basepixels_height = image_height;
3307 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);
3308 if (textureflags & TEXF_ALPHA)
3310 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3312 if (basepixels[j] < 255)
3314 skinframe->hasalpha = true;
3318 if (r_loadfog && skinframe->hasalpha)
3320 // has transparent pixels
3321 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3322 for (j = 0;j < image_width * image_height * 4;j += 4)
3327 pixels[j+3] = basepixels[j+3];
3329 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);
3333 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3335 //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]);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3337 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3338 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3339 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3345 mymiplevel = savemiplevel;
3346 if (r_loadnormalmap)
3347 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);
3348 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3350 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3351 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3352 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3353 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3356 // _norm is the name used by tenebrae and has been adopted as standard
3357 if (r_loadnormalmap && skinframe->nmap == NULL)
3359 mymiplevel = savemiplevel;
3360 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3362 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);
3366 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3368 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3369 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3370 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);
3372 Mem_Free(bumppixels);
3374 else if (r_shadow_bumpscale_basetexture.value > 0)
3376 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3377 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3378 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);
3382 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3383 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3387 // _luma is supported only for tenebrae compatibility
3388 // _glow is the preferred name
3389 mymiplevel = savemiplevel;
3390 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))))
3392 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);
3394 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3395 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3397 Mem_Free(pixels);pixels = NULL;
3400 mymiplevel = savemiplevel;
3401 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3403 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);
3405 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3406 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3412 mymiplevel = savemiplevel;
3413 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3415 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);
3417 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3418 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3424 mymiplevel = savemiplevel;
3425 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3427 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);
3429 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3430 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3436 mymiplevel = savemiplevel;
3437 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3439 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);
3441 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3442 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3449 Mem_Free(basepixels);
3454 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3455 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3458 skinframe_t *skinframe;
3461 if (cls.state == ca_dedicated)
3464 // if already loaded just return it, otherwise make a new skinframe
3465 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3466 if (skinframe->base)
3468 textureflags &= ~TEXF_FORCE_RELOAD;
3470 skinframe->stain = NULL;
3471 skinframe->merged = NULL;
3472 skinframe->base = NULL;
3473 skinframe->pants = NULL;
3474 skinframe->shirt = NULL;
3475 skinframe->nmap = NULL;
3476 skinframe->gloss = NULL;
3477 skinframe->glow = NULL;
3478 skinframe->fog = NULL;
3479 skinframe->reflect = NULL;
3480 skinframe->hasalpha = false;
3482 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3486 if (developer_loading.integer)
3487 Con_Printf("loading 32bit skin \"%s\"\n", name);
3489 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3491 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3492 unsigned char *b = a + width * height * 4;
3493 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3494 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3497 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3498 if (textureflags & TEXF_ALPHA)
3500 for (i = 3;i < width * height * 4;i += 4)
3502 if (skindata[i] < 255)
3504 skinframe->hasalpha = true;
3508 if (r_loadfog && skinframe->hasalpha)
3510 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3511 memcpy(fogpixels, skindata, width * height * 4);
3512 for (i = 0;i < width * height * 4;i += 4)
3513 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3514 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3515 Mem_Free(fogpixels);
3519 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3520 //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]);
3525 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3529 skinframe_t *skinframe;
3531 if (cls.state == ca_dedicated)
3534 // if already loaded just return it, otherwise make a new skinframe
3535 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3536 if (skinframe->base)
3538 //textureflags &= ~TEXF_FORCE_RELOAD;
3540 skinframe->stain = NULL;
3541 skinframe->merged = NULL;
3542 skinframe->base = NULL;
3543 skinframe->pants = NULL;
3544 skinframe->shirt = NULL;
3545 skinframe->nmap = NULL;
3546 skinframe->gloss = NULL;
3547 skinframe->glow = NULL;
3548 skinframe->fog = NULL;
3549 skinframe->reflect = NULL;
3550 skinframe->hasalpha = false;
3552 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3556 if (developer_loading.integer)
3557 Con_Printf("loading quake skin \"%s\"\n", name);
3559 // 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)
3560 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3561 memcpy(skinframe->qpixels, skindata, width*height);
3562 skinframe->qwidth = width;
3563 skinframe->qheight = height;
3566 for (i = 0;i < width * height;i++)
3567 featuresmask |= palette_featureflags[skindata[i]];
3569 skinframe->hasalpha = false;
3572 skinframe->hasalpha = true;
3573 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3574 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3575 skinframe->qgeneratemerged = true;
3576 skinframe->qgeneratebase = skinframe->qhascolormapping;
3577 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3579 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3580 //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]);
3585 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3589 unsigned char *skindata;
3592 if (!skinframe->qpixels)
3595 if (!skinframe->qhascolormapping)
3596 colormapped = false;
3600 if (!skinframe->qgeneratebase)
3605 if (!skinframe->qgeneratemerged)
3609 width = skinframe->qwidth;
3610 height = skinframe->qheight;
3611 skindata = skinframe->qpixels;
3613 if (skinframe->qgeneratenmap)
3615 unsigned char *a, *b;
3616 skinframe->qgeneratenmap = false;
3617 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3618 b = a + width * height * 4;
3619 // use either a custom palette or the quake palette
3620 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3621 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3622 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, b, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3626 if (skinframe->qgenerateglow)
3628 skinframe->qgenerateglow = false;
3629 if (skinframe->hasalpha) // fence textures
3630 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 | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3632 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
3637 skinframe->qgeneratebase = false;
3638 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);
3639 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);
3640 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);
3644 skinframe->qgeneratemerged = false;
3645 if (skinframe->hasalpha) // fence textures
3646 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3648 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);
3651 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3653 Mem_Free(skinframe->qpixels);
3654 skinframe->qpixels = NULL;
3658 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)
3661 skinframe_t *skinframe;
3664 if (cls.state == ca_dedicated)
3667 // if already loaded just return it, otherwise make a new skinframe
3668 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3669 if (skinframe->base)
3671 textureflags &= ~TEXF_FORCE_RELOAD;
3673 skinframe->stain = NULL;
3674 skinframe->merged = NULL;
3675 skinframe->base = NULL;
3676 skinframe->pants = NULL;
3677 skinframe->shirt = NULL;
3678 skinframe->nmap = NULL;
3679 skinframe->gloss = NULL;
3680 skinframe->glow = NULL;
3681 skinframe->fog = NULL;
3682 skinframe->reflect = NULL;
3683 skinframe->hasalpha = false;
3685 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3689 if (developer_loading.integer)
3690 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3692 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3693 if ((textureflags & TEXF_ALPHA) && alphapalette)
3695 for (i = 0;i < width * height;i++)
3697 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3699 skinframe->hasalpha = true;
3703 if (r_loadfog && skinframe->hasalpha)
3704 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3707 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3708 //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]);
3713 skinframe_t *R_SkinFrame_LoadMissing(void)
3715 skinframe_t *skinframe;
3717 if (cls.state == ca_dedicated)
3720 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3721 skinframe->stain = NULL;
3722 skinframe->merged = NULL;
3723 skinframe->base = NULL;
3724 skinframe->pants = NULL;
3725 skinframe->shirt = NULL;
3726 skinframe->nmap = NULL;
3727 skinframe->gloss = NULL;
3728 skinframe->glow = NULL;
3729 skinframe->fog = NULL;
3730 skinframe->reflect = NULL;
3731 skinframe->hasalpha = false;
3733 skinframe->avgcolor[0] = rand() / RAND_MAX;
3734 skinframe->avgcolor[1] = rand() / RAND_MAX;
3735 skinframe->avgcolor[2] = rand() / RAND_MAX;
3736 skinframe->avgcolor[3] = 1;
3741 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3744 static unsigned char pix[16][16][4];
3746 if (cls.state == ca_dedicated)
3749 // this makes a light grey/dark grey checkerboard texture
3752 for (y = 0; y < 16; y++)
3754 for (x = 0; x < 16; x++)
3756 if ((y < 8) ^ (x < 8))
3774 return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3777 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3779 skinframe_t *skinframe;
3780 if (cls.state == ca_dedicated)
3782 // if already loaded just return it, otherwise make a new skinframe
3783 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3784 if (skinframe->base)
3786 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 = (textureflags & TEXF_ALPHA) != 0;
3798 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3801 if (developer_loading.integer)
3802 Con_Printf("loading 32bit skin \"%s\"\n", name);
3803 skinframe->base = skinframe->merged = tex;
3804 Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3808 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3809 typedef struct suffixinfo_s
3812 qboolean flipx, flipy, flipdiagonal;
3815 static suffixinfo_t suffix[3][6] =
3818 {"px", false, false, false},
3819 {"nx", false, false, false},
3820 {"py", false, false, false},
3821 {"ny", false, false, false},
3822 {"pz", false, false, false},
3823 {"nz", false, false, false}
3826 {"posx", false, false, false},
3827 {"negx", false, false, false},
3828 {"posy", false, false, false},
3829 {"negy", false, false, false},
3830 {"posz", false, false, false},
3831 {"negz", false, false, false}
3834 {"rt", true, false, true},
3835 {"lf", false, true, true},
3836 {"ft", true, true, false},
3837 {"bk", false, false, false},
3838 {"up", true, false, true},
3839 {"dn", true, false, true}
3843 static int componentorder[4] = {0, 1, 2, 3};
3845 static rtexture_t *R_LoadCubemap(const char *basename)
3847 int i, j, cubemapsize;
3848 unsigned char *cubemappixels, *image_buffer;
3849 rtexture_t *cubemaptexture;
3851 // must start 0 so the first loadimagepixels has no requested width/height
3853 cubemappixels = NULL;
3854 cubemaptexture = NULL;
3855 // keep trying different suffix groups (posx, px, rt) until one loads
3856 for (j = 0;j < 3 && !cubemappixels;j++)
3858 // load the 6 images in the suffix group
3859 for (i = 0;i < 6;i++)
3861 // generate an image name based on the base and and suffix
3862 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3864 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3866 // an image loaded, make sure width and height are equal
3867 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3869 // if this is the first image to load successfully, allocate the cubemap memory
3870 if (!cubemappixels && image_width >= 1)
3872 cubemapsize = image_width;
3873 // note this clears to black, so unavailable sides are black
3874 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3876 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3878 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);
3881 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3883 Mem_Free(image_buffer);
3887 // if a cubemap loaded, upload it
3890 if (developer_loading.integer)
3891 Con_Printf("loading cubemap \"%s\"\n", basename);
3893 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);
3894 Mem_Free(cubemappixels);
3898 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3899 if (developer_loading.integer)
3901 Con_Printf("(tried tried images ");
3902 for (j = 0;j < 3;j++)
3903 for (i = 0;i < 6;i++)
3904 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3905 Con_Print(" and was unable to find any of them).\n");
3908 return cubemaptexture;
3911 rtexture_t *R_GetCubemap(const char *basename)
3914 for (i = 0;i < r_texture_numcubemaps;i++)
3915 if (r_texture_cubemaps[i] != NULL)
3916 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3917 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3918 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3919 return r_texture_whitecube;
3920 r_texture_numcubemaps++;
3921 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3922 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3923 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3924 return r_texture_cubemaps[i]->texture;
3927 static void R_Main_FreeViewCache(void)
3929 if (r_refdef.viewcache.entityvisible)
3930 Mem_Free(r_refdef.viewcache.entityvisible);
3931 if (r_refdef.viewcache.world_pvsbits)
3932 Mem_Free(r_refdef.viewcache.world_pvsbits);
3933 if (r_refdef.viewcache.world_leafvisible)
3934 Mem_Free(r_refdef.viewcache.world_leafvisible);
3935 if (r_refdef.viewcache.world_surfacevisible)
3936 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3940 static void R_Main_ResizeViewCache(void)
3942 int numentities = r_refdef.scene.numentities;
3943 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3944 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3945 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3946 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3947 if (r_refdef.viewcache.maxentities < numentities)
3949 r_refdef.viewcache.maxentities = numentities;
3950 if (r_refdef.viewcache.entityvisible)
3951 Mem_Free(r_refdef.viewcache.entityvisible);
3952 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3954 if (r_refdef.viewcache.world_numclusters != numclusters)
3956 r_refdef.viewcache.world_numclusters = numclusters;
3957 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3958 if (r_refdef.viewcache.world_pvsbits)
3959 Mem_Free(r_refdef.viewcache.world_pvsbits);
3960 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3962 if (r_refdef.viewcache.world_numleafs != numleafs)
3964 r_refdef.viewcache.world_numleafs = numleafs;
3965 if (r_refdef.viewcache.world_leafvisible)
3966 Mem_Free(r_refdef.viewcache.world_leafvisible);
3967 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3969 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3971 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3972 if (r_refdef.viewcache.world_surfacevisible)
3973 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3974 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3978 extern rtexture_t *loadingscreentexture;
3979 static void gl_main_start(void)
3981 loadingscreentexture = NULL;
3982 r_texture_blanknormalmap = NULL;
3983 r_texture_white = NULL;
3984 r_texture_grey128 = NULL;
3985 r_texture_black = NULL;
3986 r_texture_whitecube = NULL;
3987 r_texture_normalizationcube = NULL;
3988 r_texture_fogattenuation = NULL;
3989 r_texture_fogheighttexture = NULL;
3990 r_texture_gammaramps = NULL;
3991 r_texture_numcubemaps = 0;
3992 r_uniformbufferalignment = 32;
3994 r_loaddds = r_texture_dds_load.integer != 0;
3995 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3997 switch(vid.renderpath)
3999 case RENDERPATH_GL20:
4000 case RENDERPATH_D3D9:
4001 case RENDERPATH_D3D10:
4002 case RENDERPATH_D3D11:
4003 case RENDERPATH_SOFT:
4004 case RENDERPATH_GLES2:
4005 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006 Cvar_SetValueQuick(&gl_combine, 1);
4007 Cvar_SetValueQuick(&r_glsl, 1);
4008 r_loadnormalmap = true;
4011 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4012 if (vid.support.arb_uniform_buffer_object)
4013 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4016 case RENDERPATH_GL13:
4017 case RENDERPATH_GLES1:
4018 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4019 Cvar_SetValueQuick(&gl_combine, 1);
4020 Cvar_SetValueQuick(&r_glsl, 0);
4021 r_loadnormalmap = false;
4022 r_loadgloss = false;
4025 case RENDERPATH_GL11:
4026 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4027 Cvar_SetValueQuick(&gl_combine, 0);
4028 Cvar_SetValueQuick(&r_glsl, 0);
4029 r_loadnormalmap = false;
4030 r_loadgloss = false;
4036 R_FrameData_Reset();
4037 R_BufferData_Reset();
4041 memset(r_queries, 0, sizeof(r_queries));
4043 r_qwskincache = NULL;
4044 r_qwskincache_size = 0;
4046 // due to caching of texture_t references, the collision cache must be reset
4047 Collision_Cache_Reset(true);
4049 // set up r_skinframe loading system for textures
4050 memset(&r_skinframe, 0, sizeof(r_skinframe));
4051 r_skinframe.loadsequence = 1;
4052 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4054 r_main_texturepool = R_AllocTexturePool();
4055 R_BuildBlankTextures();
4057 if (vid.support.arb_texture_cube_map)
4060 R_BuildNormalizationCube();
4062 r_texture_fogattenuation = NULL;
4063 r_texture_fogheighttexture = NULL;
4064 r_texture_gammaramps = NULL;
4065 //r_texture_fogintensity = NULL;
4066 memset(&r_fb, 0, sizeof(r_fb));
4067 Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
4068 r_glsl_permutation = NULL;
4069 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4070 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4072 r_hlsl_permutation = NULL;
4073 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4074 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4076 memset(&r_svbsp, 0, sizeof (r_svbsp));
4078 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4079 r_texture_numcubemaps = 0;
4081 r_refdef.fogmasktable_density = 0;
4084 // For Steelstorm Android
4085 // FIXME CACHE the program and reload
4086 // FIXME see possible combinations for SS:BR android
4087 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4088 R_SetupShader_SetPermutationGLSL(0, 12);
4089 R_SetupShader_SetPermutationGLSL(0, 13);
4090 R_SetupShader_SetPermutationGLSL(0, 8388621);
4091 R_SetupShader_SetPermutationGLSL(3, 0);
4092 R_SetupShader_SetPermutationGLSL(3, 2048);
4093 R_SetupShader_SetPermutationGLSL(5, 0);
4094 R_SetupShader_SetPermutationGLSL(5, 2);
4095 R_SetupShader_SetPermutationGLSL(5, 2048);
4096 R_SetupShader_SetPermutationGLSL(5, 8388608);
4097 R_SetupShader_SetPermutationGLSL(11, 1);
4098 R_SetupShader_SetPermutationGLSL(11, 2049);
4099 R_SetupShader_SetPermutationGLSL(11, 8193);
4100 R_SetupShader_SetPermutationGLSL(11, 10241);
4101 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4105 static void gl_main_shutdown(void)
4107 R_RenderTarget_FreeUnused(true);
4108 Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
4110 R_FrameData_Reset();
4111 R_BufferData_Reset();
4113 R_Main_FreeViewCache();
4115 switch(vid.renderpath)
4117 case RENDERPATH_GL11:
4118 case RENDERPATH_GL13:
4119 case RENDERPATH_GL20:
4120 case RENDERPATH_GLES1:
4121 case RENDERPATH_GLES2:
4122 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4124 qglDeleteQueriesARB(r_maxqueries, r_queries);
4127 case RENDERPATH_D3D9:
4128 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4130 case RENDERPATH_D3D10:
4131 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4133 case RENDERPATH_D3D11:
4134 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4136 case RENDERPATH_SOFT:
4142 memset(r_queries, 0, sizeof(r_queries));
4144 r_qwskincache = NULL;
4145 r_qwskincache_size = 0;
4147 // clear out the r_skinframe state
4148 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4149 memset(&r_skinframe, 0, sizeof(r_skinframe));
4152 Mem_Free(r_svbsp.nodes);
4153 memset(&r_svbsp, 0, sizeof (r_svbsp));
4154 R_FreeTexturePool(&r_main_texturepool);
4155 loadingscreentexture = NULL;
4156 r_texture_blanknormalmap = NULL;
4157 r_texture_white = NULL;
4158 r_texture_grey128 = NULL;
4159 r_texture_black = NULL;
4160 r_texture_whitecube = NULL;
4161 r_texture_normalizationcube = NULL;
4162 r_texture_fogattenuation = NULL;
4163 r_texture_fogheighttexture = NULL;
4164 r_texture_gammaramps = NULL;
4165 r_texture_numcubemaps = 0;
4166 //r_texture_fogintensity = NULL;
4167 memset(&r_fb, 0, sizeof(r_fb));
4170 r_glsl_permutation = NULL;
4171 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4172 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4174 r_hlsl_permutation = NULL;
4175 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4176 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4180 static void gl_main_newmap(void)
4182 // FIXME: move this code to client
4183 char *entities, entname[MAX_QPATH];
4185 Mem_Free(r_qwskincache);
4186 r_qwskincache = NULL;
4187 r_qwskincache_size = 0;
4190 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4191 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4193 CL_ParseEntityLump(entities);
4197 if (cl.worldmodel->brush.entities)
4198 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4200 R_Main_FreeViewCache();
4202 R_FrameData_Reset();
4203 R_BufferData_Reset();
4206 void GL_Main_Init(void)
4209 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4210 R_InitShaderModeInfo();
4212 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4213 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4214 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4215 if (gamemode == GAME_NEHAHRA)
4217 Cvar_RegisterVariable (&gl_fogenable);
4218 Cvar_RegisterVariable (&gl_fogdensity);
4219 Cvar_RegisterVariable (&gl_fogred);
4220 Cvar_RegisterVariable (&gl_foggreen);
4221 Cvar_RegisterVariable (&gl_fogblue);
4222 Cvar_RegisterVariable (&gl_fogstart);
4223 Cvar_RegisterVariable (&gl_fogend);
4224 Cvar_RegisterVariable (&gl_skyclip);
4226 Cvar_RegisterVariable(&r_motionblur);
4227 Cvar_RegisterVariable(&r_damageblur);
4228 Cvar_RegisterVariable(&r_motionblur_averaging);
4229 Cvar_RegisterVariable(&r_motionblur_randomize);
4230 Cvar_RegisterVariable(&r_motionblur_minblur);
4231 Cvar_RegisterVariable(&r_motionblur_maxblur);
4232 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4233 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4234 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4235 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4236 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4237 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4238 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4239 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4240 Cvar_RegisterVariable(&r_equalize_entities_by);
4241 Cvar_RegisterVariable(&r_equalize_entities_to);
4242 Cvar_RegisterVariable(&r_depthfirst);
4243 Cvar_RegisterVariable(&r_useinfinitefarclip);
4244 Cvar_RegisterVariable(&r_farclip_base);
4245 Cvar_RegisterVariable(&r_farclip_world);
4246 Cvar_RegisterVariable(&r_nearclip);
4247 Cvar_RegisterVariable(&r_deformvertexes);
4248 Cvar_RegisterVariable(&r_transparent);
4249 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4250 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4251 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4252 Cvar_RegisterVariable(&r_showoverdraw);
4253 Cvar_RegisterVariable(&r_showbboxes);
4254 Cvar_RegisterVariable(&r_showbboxes_client);
4255 Cvar_RegisterVariable(&r_showsurfaces);
4256 Cvar_RegisterVariable(&r_showtris);
4257 Cvar_RegisterVariable(&r_shownormals);
4258 Cvar_RegisterVariable(&r_showlighting);
4259 Cvar_RegisterVariable(&r_showshadowvolumes);
4260 Cvar_RegisterVariable(&r_showcollisionbrushes);
4261 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4262 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4263 Cvar_RegisterVariable(&r_showdisabledepthtest);
4264 Cvar_RegisterVariable(&r_showspriteedges);
4265 Cvar_RegisterVariable(&r_showparticleedges);
4266 Cvar_RegisterVariable(&r_drawportals);
4267 Cvar_RegisterVariable(&r_drawentities);
4268 Cvar_RegisterVariable(&r_draw2d);
4269 Cvar_RegisterVariable(&r_drawworld);
4270 Cvar_RegisterVariable(&r_cullentities_trace);
4271 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4272 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4273 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4274 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4275 Cvar_RegisterVariable(&r_cullentities_trace_expand);
4276 Cvar_RegisterVariable(&r_cullentities_trace_pad);
4277 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4278 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4279 Cvar_RegisterVariable(&r_sortentities);
4280 Cvar_RegisterVariable(&r_drawviewmodel);
4281 Cvar_RegisterVariable(&r_drawexteriormodel);
4282 Cvar_RegisterVariable(&r_speeds);
4283 Cvar_RegisterVariable(&r_fullbrights);
4284 Cvar_RegisterVariable(&r_wateralpha);
4285 Cvar_RegisterVariable(&r_dynamic);
4286 Cvar_RegisterVariable(&r_fakelight);
4287 Cvar_RegisterVariable(&r_fakelight_intensity);
4288 Cvar_RegisterVariable(&r_fullbright_directed);
4289 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4290 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4291 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4292 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4293 Cvar_RegisterVariable(&r_fullbright);
4294 Cvar_RegisterVariable(&r_shadows);
4295 Cvar_RegisterVariable(&r_shadows_darken);
4296 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4297 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4298 Cvar_RegisterVariable(&r_shadows_throwdistance);
4299 Cvar_RegisterVariable(&r_shadows_throwdirection);
4300 Cvar_RegisterVariable(&r_shadows_focus);
4301 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4302 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4303 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4304 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4305 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4306 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4307 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4308 Cvar_RegisterVariable(&r_fog_exp2);
4309 Cvar_RegisterVariable(&r_fog_clear);
4310 Cvar_RegisterVariable(&r_drawfog);
4311 Cvar_RegisterVariable(&r_transparentdepthmasking);
4312 Cvar_RegisterVariable(&r_transparent_sortmindist);
4313 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4314 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4315 Cvar_RegisterVariable(&r_texture_dds_load);
4316 Cvar_RegisterVariable(&r_texture_dds_save);
4317 Cvar_RegisterVariable(&r_textureunits);
4318 Cvar_RegisterVariable(&gl_combine);
4319 Cvar_RegisterVariable(&r_usedepthtextures);
4320 Cvar_RegisterVariable(&r_viewfbo);
4321 Cvar_RegisterVariable(&r_rendertarget_debug);
4322 Cvar_RegisterVariable(&r_viewscale);
4323 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4324 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4325 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4326 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4327 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4328 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4329 Cvar_RegisterVariable(&r_glsl);
4330 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4331 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4332 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4333 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4334 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4335 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4336 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4337 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4338 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4339 Cvar_RegisterVariable(&r_glsl_postprocess);
4340 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4341 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4342 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4343 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4344 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4345 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4346 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4347 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4348 Cvar_RegisterVariable(&r_celshading);
4349 Cvar_RegisterVariable(&r_celoutlines);
4351 Cvar_RegisterVariable(&r_water);
4352 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4353 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4354 Cvar_RegisterVariable(&r_water_clippingplanebias);
4355 Cvar_RegisterVariable(&r_water_refractdistort);
4356 Cvar_RegisterVariable(&r_water_reflectdistort);
4357 Cvar_RegisterVariable(&r_water_scissormode);
4358 Cvar_RegisterVariable(&r_water_lowquality);
4359 Cvar_RegisterVariable(&r_water_hideplayer);
4361 Cvar_RegisterVariable(&r_lerpsprites);
4362 Cvar_RegisterVariable(&r_lerpmodels);
4363 Cvar_RegisterVariable(&r_lerplightstyles);
4364 Cvar_RegisterVariable(&r_waterscroll);
4365 Cvar_RegisterVariable(&r_bloom);
4366 Cvar_RegisterVariable(&r_bloom_colorscale);
4367 Cvar_RegisterVariable(&r_bloom_brighten);
4368 Cvar_RegisterVariable(&r_bloom_blur);
4369 Cvar_RegisterVariable(&r_bloom_resolution);
4370 Cvar_RegisterVariable(&r_bloom_colorexponent);
4371 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4372 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4373 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4374 Cvar_RegisterVariable(&r_hdr_glowintensity);
4375 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4376 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4377 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4378 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4379 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4380 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4381 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4382 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4383 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4384 Cvar_RegisterVariable(&developer_texturelogging);
4385 Cvar_RegisterVariable(&gl_lightmaps);
4386 Cvar_RegisterVariable(&r_test);
4387 Cvar_RegisterVariable(&r_batch_multidraw);
4388 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4389 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4390 Cvar_RegisterVariable(&r_glsl_skeletal);
4391 Cvar_RegisterVariable(&r_glsl_saturation);
4392 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4393 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4394 Cvar_RegisterVariable(&r_framedatasize);
4395 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4396 Cvar_RegisterVariable(&r_buffermegs[i]);
4397 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4398 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4399 Cvar_SetValue("r_fullbrights", 0);
4400 #ifdef DP_MOBILETOUCH
4401 // GLES devices have terrible depth precision in general, so...
4402 Cvar_SetValueQuick(&r_nearclip, 4);
4403 Cvar_SetValueQuick(&r_farclip_base, 4096);
4404 Cvar_SetValueQuick(&r_farclip_world, 0);
4405 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4407 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4410 void Render_Init(void)
4423 R_LightningBeams_Init();
4433 extern char *ENGINE_EXTENSIONS;
4436 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4437 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4438 gl_version = (const char *)qglGetString(GL_VERSION);
4439 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4443 if (!gl_platformextensions)
4444 gl_platformextensions = "";
4446 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4447 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4448 Con_Printf("GL_VERSION: %s\n", gl_version);
4449 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4450 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4452 VID_CheckExtensions();
4454 // LordHavoc: report supported extensions
4456 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4458 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4461 // clear to black (loading plaque will be seen over this)
4462 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4466 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4470 if (r_trippy.integer)
4472 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4474 p = r_refdef.view.frustum + i;
4479 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4483 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4487 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4491 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4495 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4499 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4503 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4507 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4515 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4519 if (r_trippy.integer)
4521 for (i = 0;i < numplanes;i++)
4528 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4532 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4536 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4540 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4544 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4548 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4552 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4556 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4564 //==================================================================================
4566 // LordHavoc: this stores temporary data used within the same frame
4568 typedef struct r_framedata_mem_s
4570 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4571 size_t size; // how much usable space
4572 size_t current; // how much space in use
4573 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4574 size_t wantedsize; // how much space was allocated
4575 unsigned char *data; // start of real data (16byte aligned)
4579 static r_framedata_mem_t *r_framedata_mem;
4581 void R_FrameData_Reset(void)
4583 while (r_framedata_mem)
4585 r_framedata_mem_t *next = r_framedata_mem->purge;
4586 Mem_Free(r_framedata_mem);
4587 r_framedata_mem = next;
4591 static void R_FrameData_Resize(qboolean mustgrow)
4594 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4595 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4596 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4598 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4599 newmem->wantedsize = wantedsize;
4600 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4601 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4602 newmem->current = 0;
4604 newmem->purge = r_framedata_mem;
4605 r_framedata_mem = newmem;
4609 void R_FrameData_NewFrame(void)
4611 R_FrameData_Resize(false);
4612 if (!r_framedata_mem)
4614 // if we ran out of space on the last frame, free the old memory now
4615 while (r_framedata_mem->purge)
4617 // repeatedly remove the second item in the list, leaving only head
4618 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4619 Mem_Free(r_framedata_mem->purge);
4620 r_framedata_mem->purge = next;
4622 // reset the current mem pointer
4623 r_framedata_mem->current = 0;
4624 r_framedata_mem->mark = 0;
4627 void *R_FrameData_Alloc(size_t size)
4632 // align to 16 byte boundary - the data pointer is already aligned, so we
4633 // only need to ensure the size of every allocation is also aligned
4634 size = (size + 15) & ~15;
4636 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4638 // emergency - we ran out of space, allocate more memory
4639 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4640 newvalue = r_framedatasize.value * 2.0f;
4641 // upper bound based on architecture - if we try to allocate more than this we could overflow, better to loop until we error out on allocation failure
4642 if (sizeof(size_t) >= 8)
4643 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4645 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4646 // this might not be a growing it, but we'll allocate another buffer every time
4647 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4648 R_FrameData_Resize(true);
4651 data = r_framedata_mem->data + r_framedata_mem->current;
4652 r_framedata_mem->current += size;
4654 // count the usage for stats
4655 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4656 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4658 return (void *)data;
4661 void *R_FrameData_Store(size_t size, void *data)
4663 void *d = R_FrameData_Alloc(size);
4665 memcpy(d, data, size);
4669 void R_FrameData_SetMark(void)
4671 if (!r_framedata_mem)
4673 r_framedata_mem->mark = r_framedata_mem->current;
4676 void R_FrameData_ReturnToMark(void)
4678 if (!r_framedata_mem)
4680 r_framedata_mem->current = r_framedata_mem->mark;
4683 //==================================================================================
4685 // avoid reusing the same buffer objects on consecutive frames
4686 #define R_BUFFERDATA_CYCLE 3
4688 typedef struct r_bufferdata_buffer_s
4690 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4691 size_t size; // how much usable space
4692 size_t current; // how much space in use
4693 r_meshbuffer_t *buffer; // the buffer itself
4695 r_bufferdata_buffer_t;
4697 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4698 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4700 /// frees all dynamic buffers
4701 void R_BufferData_Reset(void)
4704 r_bufferdata_buffer_t **p, *mem;
4705 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4707 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4710 p = &r_bufferdata_buffer[cycle][type];
4716 R_Mesh_DestroyMeshBuffer(mem->buffer);
4723 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4724 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4726 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4728 float newvalue = r_buffermegs[type].value;
4730 // increase the cvar if we have to (but only if we already have a mem)
4731 if (mustgrow && mem)
4733 newvalue = bound(0.25f, newvalue, 256.0f);
4734 while (newvalue * 1024*1024 < minsize)
4737 // clamp the cvar to valid range
4738 newvalue = bound(0.25f, newvalue, 256.0f);
4739 if (r_buffermegs[type].value != newvalue)
4740 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4742 // calculate size in bytes
4743 size = (size_t)(newvalue * 1024*1024);
4744 size = bound(131072, size, 256*1024*1024);
4746 // allocate a new buffer if the size is different (purge old one later)
4747 // or if we were told we must grow the buffer
4748 if (!mem || mem->size != size || mustgrow)
4750 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4753 if (type == R_BUFFERDATA_VERTEX)
4754 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4755 else if (type == R_BUFFERDATA_INDEX16)
4756 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4757 else if (type == R_BUFFERDATA_INDEX32)
4758 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4759 else if (type == R_BUFFERDATA_UNIFORM)
4760 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4761 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4762 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4766 void R_BufferData_NewFrame(void)
4769 r_bufferdata_buffer_t **p, *mem;
4770 // cycle to the next frame's buffers
4771 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4772 // if we ran out of space on the last time we used these buffers, free the old memory now
4773 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4775 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4777 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4778 // free all but the head buffer, this is how we recycle obsolete
4779 // buffers after they are no longer in use
4780 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4786 R_Mesh_DestroyMeshBuffer(mem->buffer);
4789 // reset the current offset
4790 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4795 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4797 r_bufferdata_buffer_t *mem;
4801 *returnbufferoffset = 0;
4803 // align size to a byte boundary appropriate for the buffer type, this
4804 // makes all allocations have aligned start offsets
4805 if (type == R_BUFFERDATA_UNIFORM)
4806 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4808 padsize = (datasize + 15) & ~15;
4810 // if we ran out of space in this buffer we must allocate a new one
4811 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)
4812 R_BufferData_Resize(type, true, padsize);
4814 // if the resize did not give us enough memory, fail
4815 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)
4816 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4818 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4819 offset = (int)mem->current;
4820 mem->current += padsize;
4822 // upload the data to the buffer at the chosen offset
4824 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4825 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4827 // count the usage for stats
4828 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4829 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4831 // return the buffer offset
4832 *returnbufferoffset = offset;
4837 //==================================================================================
4839 // LordHavoc: animcache originally written by Echon, rewritten since then
4842 * Animation cache prevents re-generating mesh data for an animated model
4843 * multiple times in one frame for lighting, shadowing, reflections, etc.
4846 void R_AnimCache_Free(void)
4850 void R_AnimCache_ClearCache(void)
4853 entity_render_t *ent;
4855 for (i = 0;i < r_refdef.scene.numentities;i++)
4857 ent = r_refdef.scene.entities[i];
4858 ent->animcache_vertex3f = NULL;
4859 ent->animcache_vertex3f_vertexbuffer = NULL;
4860 ent->animcache_vertex3f_bufferoffset = 0;
4861 ent->animcache_normal3f = NULL;
4862 ent->animcache_normal3f_vertexbuffer = NULL;
4863 ent->animcache_normal3f_bufferoffset = 0;
4864 ent->animcache_svector3f = NULL;
4865 ent->animcache_svector3f_vertexbuffer = NULL;
4866 ent->animcache_svector3f_bufferoffset = 0;
4867 ent->animcache_tvector3f = NULL;
4868 ent->animcache_tvector3f_vertexbuffer = NULL;
4869 ent->animcache_tvector3f_bufferoffset = 0;
4870 ent->animcache_vertexmesh = NULL;
4871 ent->animcache_vertexmesh_vertexbuffer = NULL;
4872 ent->animcache_vertexmesh_bufferoffset = 0;
4873 ent->animcache_skeletaltransform3x4 = NULL;
4874 ent->animcache_skeletaltransform3x4buffer = NULL;
4875 ent->animcache_skeletaltransform3x4offset = 0;
4876 ent->animcache_skeletaltransform3x4size = 0;
4880 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4884 // check if we need the meshbuffers
4885 if (!vid.useinterleavedarrays)
4888 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4889 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4890 // TODO: upload vertexbuffer?
4891 if (ent->animcache_vertexmesh)
4893 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4894 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4895 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4896 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4897 for (i = 0;i < numvertices;i++)
4898 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4899 if (ent->animcache_svector3f)
4900 for (i = 0;i < numvertices;i++)
4901 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4902 if (ent->animcache_tvector3f)
4903 for (i = 0;i < numvertices;i++)
4904 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4905 if (ent->animcache_normal3f)
4906 for (i = 0;i < numvertices;i++)
4907 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4911 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4913 dp_model_t *model = ent->model;
4916 // see if this ent is worth caching
4917 if (!model || !model->Draw || !model->AnimateVertices)
4919 // nothing to cache if it contains no animations and has no skeleton
4920 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4922 // see if it is already cached for gpuskeletal
4923 if (ent->animcache_skeletaltransform3x4)
4925 // see if it is already cached as a mesh
4926 if (ent->animcache_vertex3f)
4928 // check if we need to add normals or tangents
4929 if (ent->animcache_normal3f)
4930 wantnormals = false;
4931 if (ent->animcache_svector3f)
4932 wanttangents = false;
4933 if (!wantnormals && !wanttangents)
4937 // check which kind of cache we need to generate
4938 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4940 // cache the skeleton so the vertex shader can use it
4941 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4942 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4943 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4944 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4945 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4946 // note: this can fail if the buffer is at the grow limit
4947 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4948 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4950 else if (ent->animcache_vertex3f)
4952 // mesh was already cached but we may need to add normals/tangents
4953 // (this only happens with multiple views, reflections, cameras, etc)
4954 if (wantnormals || wanttangents)
4956 numvertices = model->surfmesh.num_vertices;
4958 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4961 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4962 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4964 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4965 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4966 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4967 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4968 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4973 // generate mesh cache
4974 numvertices = model->surfmesh.num_vertices;
4975 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4980 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4983 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4984 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985 if (wantnormals || wanttangents)
4987 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4988 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4989 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4991 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4992 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4993 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4998 void R_AnimCache_CacheVisibleEntities(void)
5001 qboolean wantnormals = true;
5002 qboolean wanttangents = !r_showsurfaces.integer;
5004 switch(vid.renderpath)
5006 case RENDERPATH_GL20:
5007 case RENDERPATH_D3D9:
5008 case RENDERPATH_D3D10:
5009 case RENDERPATH_D3D11:
5010 case RENDERPATH_GLES2:
5012 case RENDERPATH_GL11:
5013 case RENDERPATH_GL13:
5014 case RENDERPATH_GLES1:
5015 wanttangents = false;
5017 case RENDERPATH_SOFT:
5021 if (r_shownormals.integer)
5022 wanttangents = wantnormals = true;
5024 // TODO: thread this
5025 // NOTE: R_PrepareRTLights() also caches entities
5027 for (i = 0;i < r_refdef.scene.numentities;i++)
5028 if (r_refdef.viewcache.entityvisible[i])
5029 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5032 //==================================================================================
5034 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t entboxexpand, vec_t pad, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5037 vec3_t eyemins, eyemaxs;
5038 vec3_t boxmins, boxmaxs;
5039 vec3_t padmins, padmaxs;
5042 dp_model_t *model = r_refdef.scene.worldmodel;
5043 static vec3_t positions[] = {
5044 { 0.5f, 0.5f, 0.5f },
5045 { 0.0f, 0.0f, 0.0f },
5046 { 0.0f, 0.0f, 1.0f },
5047 { 0.0f, 1.0f, 0.0f },
5048 { 0.0f, 1.0f, 1.0f },
5049 { 1.0f, 0.0f, 0.0f },
5050 { 1.0f, 0.0f, 1.0f },
5051 { 1.0f, 1.0f, 0.0f },
5052 { 1.0f, 1.0f, 1.0f },
5055 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5059 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5060 if (!r_refdef.view.usevieworiginculling)
5063 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5066 // expand the eye box a little
5067 eyemins[0] = eye[0] - eyejitter;
5068 eyemaxs[0] = eye[0] + eyejitter;
5069 eyemins[1] = eye[1] - eyejitter;
5070 eyemaxs[1] = eye[1] + eyejitter;
5071 eyemins[2] = eye[2] - eyejitter;
5072 eyemaxs[2] = eye[2] + eyejitter;
5073 // expand the box a little
5074 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
5075 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
5076 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
5077 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
5078 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
5079 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
5080 // make an even larger box for the acceptable area
5081 padmins[0] = boxmins[0] - pad;
5082 padmaxs[0] = boxmaxs[0] + pad;
5083 padmins[1] = boxmins[1] - pad;
5084 padmaxs[1] = boxmaxs[1] + pad;
5085 padmins[2] = boxmins[2] - pad;
5086 padmaxs[2] = boxmaxs[2] + pad;
5088 // return true if eye overlaps enlarged box
5089 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5092 // try specific positions in the box first - note that these can be cached
5093 if (r_cullentities_trace_entityocclusion.integer)
5095 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5097 VectorCopy(eye, start);
5098 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5099 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5100 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5101 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5102 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5103 // not picky - if the trace ended anywhere in the box we're good
5104 if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5108 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5111 // try various random positions
5112 for (i = 0; i < numsamples; i++)
5114 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5115 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5116 if (r_cullentities_trace_entityocclusion.integer)
5118 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5119 // not picky - if the trace ended anywhere in the box we're good
5120 if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5123 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5131 static void R_View_UpdateEntityVisible (void)
5136 entity_render_t *ent;
5138 if (r_refdef.envmap || r_fb.water.hideplayer)
5139 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5140 else if (chase_active.integer || r_fb.water.renderingscene)
5141 renderimask = RENDER_VIEWMODEL;
5143 renderimask = RENDER_EXTERIORMODEL;
5144 if (!r_drawviewmodel.integer)
5145 renderimask |= RENDER_VIEWMODEL;
5146 if (!r_drawexteriormodel.integer)
5147 renderimask |= RENDER_EXTERIORMODEL;
5148 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5149 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5151 // worldmodel can check visibility
5152 for (i = 0;i < r_refdef.scene.numentities;i++)
5154 ent = r_refdef.scene.entities[i];
5155 if (!(ent->flags & renderimask))
5156 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)))
5157 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))
5158 r_refdef.viewcache.entityvisible[i] = true;
5163 // no worldmodel or it can't check visibility
5164 for (i = 0;i < r_refdef.scene.numentities;i++)
5166 ent = r_refdef.scene.entities[i];
5167 if (!(ent->flags & renderimask))
5168 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)))
5169 r_refdef.viewcache.entityvisible[i] = true;
5172 if (r_cullentities_trace.integer)
5174 for (i = 0;i < r_refdef.scene.numentities;i++)
5176 if (!r_refdef.viewcache.entityvisible[i])
5178 ent = r_refdef.scene.entities[i];
5179 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5181 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5182 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_cullentities_trace_expand.value, r_cullentities_trace_pad.value, r_refdef.view.origin, ent->mins, ent->maxs))
5183 ent->last_trace_visibility = realtime;
5184 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5185 r_refdef.viewcache.entityvisible[i] = 0;
5191 /// only used if skyrendermasked, and normally returns false
5192 static int R_DrawBrushModelsSky (void)
5195 entity_render_t *ent;
5198 for (i = 0;i < r_refdef.scene.numentities;i++)
5200 if (!r_refdef.viewcache.entityvisible[i])
5202 ent = r_refdef.scene.entities[i];
5203 if (!ent->model || !ent->model->DrawSky)
5205 ent->model->DrawSky(ent);
5211 static void R_DrawNoModel(entity_render_t *ent);
5212 static void R_DrawModels(void)
5215 entity_render_t *ent;
5217 for (i = 0;i < r_refdef.scene.numentities;i++)
5219 if (!r_refdef.viewcache.entityvisible[i])
5221 ent = r_refdef.scene.entities[i];
5222 r_refdef.stats[r_stat_entities]++;
5224 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5227 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5228 Con_Printf("R_DrawModels\n");
5229 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]);
5230 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);
5231 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);
5234 if (ent->model && ent->model->Draw != NULL)
5235 ent->model->Draw(ent);
5241 static void R_DrawModelsDepth(void)
5244 entity_render_t *ent;
5246 for (i = 0;i < r_refdef.scene.numentities;i++)
5248 if (!r_refdef.viewcache.entityvisible[i])
5250 ent = r_refdef.scene.entities[i];
5251 if (ent->model && ent->model->DrawDepth != NULL)
5252 ent->model->DrawDepth(ent);
5256 static void R_DrawModelsDebug(void)
5259 entity_render_t *ent;
5261 for (i = 0;i < r_refdef.scene.numentities;i++)
5263 if (!r_refdef.viewcache.entityvisible[i])
5265 ent = r_refdef.scene.entities[i];
5266 if (ent->model && ent->model->DrawDebug != NULL)
5267 ent->model->DrawDebug(ent);
5271 static void R_DrawModelsAddWaterPlanes(void)
5274 entity_render_t *ent;
5276 for (i = 0;i < r_refdef.scene.numentities;i++)
5278 if (!r_refdef.viewcache.entityvisible[i])
5280 ent = r_refdef.scene.entities[i];
5281 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5282 ent->model->DrawAddWaterPlanes(ent);
5286 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}};
5288 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5290 if (r_hdr_irisadaptation.integer)
5295 vec3_t diffusenormal;
5297 vec_t brightness = 0.0f;
5302 VectorCopy(r_refdef.view.forward, forward);
5303 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5305 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5306 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5307 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5308 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5309 d = DotProduct(forward, diffusenormal);
5310 brightness += VectorLength(ambient);
5312 brightness += d * VectorLength(diffuse);
5314 brightness *= 1.0f / c;
5315 brightness += 0.00001f; // make sure it's never zero
5316 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5317 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5318 current = r_hdr_irisadaptation_value.value;
5320 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5321 else if (current > goal)
5322 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5323 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5324 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5326 else if (r_hdr_irisadaptation_value.value != 1.0f)
5327 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5330 static void R_View_SetFrustum(const int *scissor)
5333 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5334 vec3_t forward, left, up, origin, v;
5338 // flipped x coordinates (because x points left here)
5339 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5340 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5342 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5343 switch(vid.renderpath)
5345 case RENDERPATH_D3D9:
5346 case RENDERPATH_D3D10:
5347 case RENDERPATH_D3D11:
5348 // non-flipped y coordinates
5349 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5350 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5352 case RENDERPATH_SOFT:
5353 case RENDERPATH_GL11:
5354 case RENDERPATH_GL13:
5355 case RENDERPATH_GL20:
5356 case RENDERPATH_GLES1:
5357 case RENDERPATH_GLES2:
5358 // non-flipped y coordinates
5359 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5360 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5365 // we can't trust r_refdef.view.forward and friends in reflected scenes
5366 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5369 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5370 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5371 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5372 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5373 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5374 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5375 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5376 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5377 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5378 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5379 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5380 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5384 zNear = r_refdef.nearclip;
5385 nudge = 1.0 - 1.0 / (1<<23);
5386 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5387 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5388 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5389 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5390 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5391 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5392 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5393 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5399 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5400 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5401 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5402 r_refdef.view.frustum[0].dist = m[15] - m[12];
5404 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5405 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5406 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5407 r_refdef.view.frustum[1].dist = m[15] + m[12];
5409 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5410 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5411 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5412 r_refdef.view.frustum[2].dist = m[15] - m[13];
5414 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5415 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5416 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5417 r_refdef.view.frustum[3].dist = m[15] + m[13];
5419 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5420 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5421 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5422 r_refdef.view.frustum[4].dist = m[15] - m[14];
5424 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5425 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5426 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5427 r_refdef.view.frustum[5].dist = m[15] + m[14];
5430 if (r_refdef.view.useperspective)
5432 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5433 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]);
5434 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]);
5435 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]);
5436 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]);
5438 // then the normals from the corners relative to origin
5439 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5440 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5441 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5442 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5444 // in a NORMAL view, forward cross left == up
5445 // in a REFLECTED view, forward cross left == down
5446 // so our cross products above need to be adjusted for a left handed coordinate system
5447 CrossProduct(forward, left, v);
5448 if(DotProduct(v, up) < 0)
5450 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5451 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5452 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5453 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5456 // Leaving those out was a mistake, those were in the old code, and they
5457 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5458 // I couldn't reproduce it after adding those normalizations. --blub
5459 VectorNormalize(r_refdef.view.frustum[0].normal);
5460 VectorNormalize(r_refdef.view.frustum[1].normal);
5461 VectorNormalize(r_refdef.view.frustum[2].normal);
5462 VectorNormalize(r_refdef.view.frustum[3].normal);
5464 // make the corners absolute
5465 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5466 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5467 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5468 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5471 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5473 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5474 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5475 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5476 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5477 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5481 VectorScale(left, -1.0f, r_refdef.view.frustum[0].normal);
5482 VectorScale(left, 1.0f, r_refdef.view.frustum[1].normal);
5483 VectorScale(up, -1.0f, r_refdef.view.frustum[2].normal);
5484 VectorScale(up, 1.0f, r_refdef.view.frustum[3].normal);
5485 VectorScale(forward, -1.0f, r_refdef.view.frustum[4].normal);
5486 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
5487 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
5488 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
5489 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
5490 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) - r_refdef.farclip;
5492 r_refdef.view.numfrustumplanes = 5;
5494 if (r_refdef.view.useclipplane)
5496 r_refdef.view.numfrustumplanes = 6;
5497 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5500 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5501 PlaneClassify(r_refdef.view.frustum + i);
5503 // LordHavoc: note to all quake engine coders, Quake had a special case
5504 // for 90 degrees which assumed a square view (wrong), so I removed it,
5505 // Quake2 has it disabled as well.
5507 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5508 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5509 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5510 //PlaneClassify(&frustum[0]);
5512 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5513 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5514 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5515 //PlaneClassify(&frustum[1]);
5517 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5518 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5519 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5520 //PlaneClassify(&frustum[2]);
5522 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5523 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5524 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5525 //PlaneClassify(&frustum[3]);
5528 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5529 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5530 //PlaneClassify(&frustum[4]);
5533 static void R_View_UpdateWithScissor(const int *myscissor)
5535 R_Main_ResizeViewCache();
5536 R_View_SetFrustum(myscissor);
5537 R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
5538 R_View_UpdateEntityVisible();
5541 static void R_View_Update(void)
5543 R_Main_ResizeViewCache();
5544 R_View_SetFrustum(NULL);
5545 R_View_WorldVisibility(!r_refdef.view.usevieworiginculling);
5546 R_View_UpdateEntityVisible();
5549 float viewscalefpsadjusted = 1.0f;
5551 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5553 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5554 scale = bound(0.03125f, scale, 1.0f);
5555 *outwidth = (int)ceil(width * scale);
5556 *outheight = (int)ceil(height * scale);
5559 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5561 const float *customclipplane = NULL;
5563 int /*rtwidth,*/ rtheight;
5564 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5566 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5567 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5568 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5569 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5570 dist = r_refdef.view.clipplane.dist;
5571 plane[0] = r_refdef.view.clipplane.normal[0];
5572 plane[1] = r_refdef.view.clipplane.normal[1];
5573 plane[2] = r_refdef.view.clipplane.normal[2];
5575 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5578 //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5579 rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5581 if (!r_refdef.view.useperspective)
5582 R_Viewport_InitOrtho3D(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5583 else if (vid.stencil && r_useinfinitefarclip.integer)
5584 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5586 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5587 R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5588 R_SetViewport(&r_refdef.view.viewport);
5589 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5591 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5592 float screenplane[4];
5593 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5594 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5595 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5596 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5597 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5601 void R_EntityMatrix(const matrix4x4_t *matrix)
5603 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5605 gl_modelmatrixchanged = false;
5606 gl_modelmatrix = *matrix;
5607 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5608 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5609 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5610 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5612 switch(vid.renderpath)
5614 case RENDERPATH_D3D9:
5616 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5617 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5620 case RENDERPATH_D3D10:
5621 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5623 case RENDERPATH_D3D11:
5624 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5626 case RENDERPATH_GL11:
5627 case RENDERPATH_GL13:
5628 case RENDERPATH_GLES1:
5630 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5633 case RENDERPATH_SOFT:
5634 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5635 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5637 case RENDERPATH_GL20:
5638 case RENDERPATH_GLES2:
5639 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5640 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5646 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5648 r_viewport_t viewport;
5652 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5653 R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5654 R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5655 R_SetViewport(&viewport);
5656 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5657 GL_Color(1, 1, 1, 1);
5658 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5659 GL_BlendFunc(GL_ONE, GL_ZERO);
5660 GL_ScissorTest(false);
5661 GL_DepthMask(false);
5662 GL_DepthRange(0, 1);
5663 GL_DepthTest(false);
5664 GL_DepthFunc(GL_LEQUAL);
5665 R_EntityMatrix(&identitymatrix);
5666 R_Mesh_ResetTextureState();
5667 GL_PolygonOffset(0, 0);
5668 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5669 switch(vid.renderpath)
5671 case RENDERPATH_GL11:
5672 case RENDERPATH_GL13:
5673 case RENDERPATH_GL20:
5674 case RENDERPATH_GLES1:
5675 case RENDERPATH_GLES2:
5676 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5678 case RENDERPATH_D3D9:
5679 case RENDERPATH_D3D10:
5680 case RENDERPATH_D3D11:
5681 case RENDERPATH_SOFT:
5684 GL_CullFace(GL_NONE);
5689 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5691 R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5694 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5696 R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5697 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5698 GL_Color(1, 1, 1, 1);
5699 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5700 GL_BlendFunc(GL_ONE, GL_ZERO);
5701 GL_ScissorTest(true);
5703 GL_DepthRange(0, 1);
5705 GL_DepthFunc(GL_LEQUAL);
5706 R_EntityMatrix(&identitymatrix);
5707 R_Mesh_ResetTextureState();
5708 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5709 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5710 switch(vid.renderpath)
5712 case RENDERPATH_GL11:
5713 case RENDERPATH_GL13:
5714 case RENDERPATH_GL20:
5715 case RENDERPATH_GLES1:
5716 case RENDERPATH_GLES2:
5717 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5719 case RENDERPATH_D3D9:
5720 case RENDERPATH_D3D10:
5721 case RENDERPATH_D3D11:
5722 case RENDERPATH_SOFT:
5725 GL_CullFace(r_refdef.view.cullface_back);
5730 R_RenderView_UpdateViewVectors
5733 void R_RenderView_UpdateViewVectors(void)
5735 // break apart the view matrix into vectors for various purposes
5736 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5737 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5738 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5739 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5740 // make an inverted copy of the view matrix for tracking sprites
5741 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5744 void R_RenderTarget_FreeUnused(qboolean force)
5747 end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5748 for (i = 0; i < end; i++)
5750 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5751 // free resources for rendertargets that have not been used for a while
5752 // (note: this check is run after the frame render, so any targets used
5753 // this frame will not be affected even at low framerates)
5754 if (r && (realtime - r->lastusetime > 0.2 || force))
5757 R_Mesh_DestroyFramebufferObject(r->fbo);
5758 for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
5759 if (r->colortexture[j])
5760 R_FreeTexture(r->colortexture[j]);
5761 if (r->depthtexture)
5762 R_FreeTexture(r->depthtexture);
5763 Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
5768 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
5770 float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
5771 switch (vid.renderpath)
5773 case RENDERPATH_D3D9:
5774 x1 = (x + 0.5f) * iw;
5775 x2 = (x + 0.5f + w) * iw;
5776 y1 = (y + 0.5f) * ih;
5777 y2 = (y + 0.5f + h) * ih;
5783 y2 = (th - y - h) * ih;
5796 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
5799 r_rendertarget_t *r = NULL;
5801 // first try to reuse an existing slot if possible
5802 end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5803 for (i = 0; i < end; i++)
5805 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5806 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
5811 // no unused exact match found, so we have to make one in the first unused slot
5812 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
5813 r->texturewidth = texturewidth;
5814 r->textureheight = textureheight;
5815 r->colortextype[0] = colortextype0;
5816 r->colortextype[1] = colortextype1;
5817 r->colortextype[2] = colortextype2;
5818 r->colortextype[3] = colortextype3;
5819 r->depthtextype = depthtextype;
5820 r->depthisrenderbuffer = depthisrenderbuffer;
5821 for (j = 0; j < 4; j++)
5822 if (r->colortextype[j])
5823 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5824 if (r->depthtextype)
5826 if (r->depthisrenderbuffer)
5827 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
5829 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5831 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
5833 r_refdef.stats[r_stat_rendertargets_used]++;
5834 r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
5835 r->lastusetime = realtime;
5836 R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
5840 static void R_Water_StartFrame(void)
5842 int waterwidth, waterheight;
5844 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5847 switch(vid.renderpath)
5849 case RENDERPATH_GL20:
5850 case RENDERPATH_D3D9:
5851 case RENDERPATH_D3D10:
5852 case RENDERPATH_D3D11:
5853 case RENDERPATH_SOFT:
5854 case RENDERPATH_GLES2:
5856 case RENDERPATH_GL11:
5857 case RENDERPATH_GL13:
5858 case RENDERPATH_GLES1:
5862 // set waterwidth and waterheight to the water resolution that will be
5863 // used (often less than the screen resolution for faster rendering)
5864 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5865 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5866 R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
5868 if (!r_water.integer || r_showsurfaces.integer)
5869 waterwidth = waterheight = 0;
5871 // set up variables that will be used in shader setup
5872 r_fb.water.waterwidth = waterwidth;
5873 r_fb.water.waterheight = waterheight;
5874 r_fb.water.texturewidth = waterwidth;
5875 r_fb.water.textureheight = waterheight;
5876 r_fb.water.camerawidth = waterwidth;
5877 r_fb.water.cameraheight = waterheight;
5878 r_fb.water.screenscale[0] = 0.5f;
5879 r_fb.water.screenscale[1] = 0.5f;
5880 r_fb.water.screencenter[0] = 0.5f;
5881 r_fb.water.screencenter[1] = 0.5f;
5882 r_fb.water.enabled = waterwidth != 0;
5884 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5885 r_fb.water.numwaterplanes = 0;
5888 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5890 int planeindex, bestplaneindex, vertexindex;
5891 vec3_t mins, maxs, normal, center, v, n;
5892 vec_t planescore, bestplanescore;
5894 r_waterstate_waterplane_t *p;
5895 texture_t *t = R_GetCurrentTexture(surface->texture);
5897 rsurface.texture = t;
5898 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5899 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5900 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5902 // average the vertex normals, find the surface bounds (after deformvertexes)
5903 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5904 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5905 VectorCopy(n, normal);
5906 VectorCopy(v, mins);
5907 VectorCopy(v, maxs);
5908 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5910 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5911 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5912 VectorAdd(normal, n, normal);
5913 mins[0] = min(mins[0], v[0]);
5914 mins[1] = min(mins[1], v[1]);
5915 mins[2] = min(mins[2], v[2]);
5916 maxs[0] = max(maxs[0], v[0]);
5917 maxs[1] = max(maxs[1], v[1]);
5918 maxs[2] = max(maxs[2], v[2]);
5920 VectorNormalize(normal);
5921 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5923 VectorCopy(normal, plane.normal);
5924 VectorNormalize(plane.normal);
5925 plane.dist = DotProduct(center, plane.normal);
5926 PlaneClassify(&plane);
5927 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5929 // skip backfaces (except if nocullface is set)
5930 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5932 VectorNegate(plane.normal, plane.normal);
5934 PlaneClassify(&plane);
5938 // find a matching plane if there is one
5939 bestplaneindex = -1;
5940 bestplanescore = 1048576.0f;
5941 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5943 if(p->camera_entity == t->camera_entity)
5945 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5946 if (bestplaneindex < 0 || bestplanescore > planescore)
5948 bestplaneindex = planeindex;
5949 bestplanescore = planescore;
5953 planeindex = bestplaneindex;
5955 // if this surface does not fit any known plane rendered this frame, add one
5956 if (planeindex < 0 || bestplanescore > 0.001f)
5958 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5960 // store the new plane
5961 planeindex = r_fb.water.numwaterplanes++;
5962 p = r_fb.water.waterplanes + planeindex;
5964 // clear materialflags and pvs
5965 p->materialflags = 0;
5966 p->pvsvalid = false;
5967 p->camera_entity = t->camera_entity;
5968 VectorCopy(mins, p->mins);
5969 VectorCopy(maxs, p->maxs);
5973 // We're totally screwed.
5979 // merge mins/maxs when we're adding this surface to the plane
5980 p = r_fb.water.waterplanes + planeindex;
5981 p->mins[0] = min(p->mins[0], mins[0]);
5982 p->mins[1] = min(p->mins[1], mins[1]);
5983 p->mins[2] = min(p->mins[2], mins[2]);
5984 p->maxs[0] = max(p->maxs[0], maxs[0]);
5985 p->maxs[1] = max(p->maxs[1], maxs[1]);
5986 p->maxs[2] = max(p->maxs[2], maxs[2]);
5988 // merge this surface's materialflags into the waterplane
5989 p->materialflags |= t->currentmaterialflags;
5990 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5992 // merge this surface's PVS into the waterplane
5993 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5994 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5996 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6002 extern cvar_t r_drawparticles;
6003 extern cvar_t r_drawdecals;
6005 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
6008 r_refdef_view_t originalview;
6009 r_refdef_view_t myview;
6010 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;
6011 r_waterstate_waterplane_t *p;
6013 r_rendertarget_t *rt;
6015 originalview = r_refdef.view;
6017 // lowquality hack, temporarily shut down some cvars and restore afterwards
6018 qualityreduction = r_water_lowquality.integer;
6019 if (qualityreduction > 0)
6021 if (qualityreduction >= 1)
6023 old_r_shadows = r_shadows.integer;
6024 old_r_worldrtlight = r_shadow_realtime_world.integer;
6025 old_r_dlight = r_shadow_realtime_dlight.integer;
6026 Cvar_SetValueQuick(&r_shadows, 0);
6027 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6028 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6030 if (qualityreduction >= 2)
6032 old_r_dynamic = r_dynamic.integer;
6033 old_r_particles = r_drawparticles.integer;
6034 old_r_decals = r_drawdecals.integer;
6035 Cvar_SetValueQuick(&r_dynamic, 0);
6036 Cvar_SetValueQuick(&r_drawparticles, 0);
6037 Cvar_SetValueQuick(&r_drawdecals, 0);
6041 for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
6043 p->rt_reflection = NULL;
6044 p->rt_refraction = NULL;
6045 p->rt_camera = NULL;
6049 r_refdef.view = originalview;
6050 r_refdef.view.showdebug = false;
6051 r_refdef.view.width = r_fb.water.waterwidth;
6052 r_refdef.view.height = r_fb.water.waterheight;
6053 r_refdef.view.useclipplane = true;
6054 myview = r_refdef.view;
6055 r_fb.water.renderingscene = true;
6056 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6058 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6061 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6063 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6064 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6066 r_refdef.view = myview;
6067 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6068 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6069 if(r_water_scissormode.integer)
6071 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6072 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6074 p->rt_reflection = NULL;
6075 p->rt_refraction = NULL;
6076 p->rt_camera = NULL;
6081 r_refdef.view.clipplane = p->plane;
6082 // reflected view origin may be in solid, so don't cull with it
6083 r_refdef.view.usevieworiginculling = false;
6084 // reverse the cullface settings for this render
6085 r_refdef.view.cullface_front = GL_FRONT;
6086 r_refdef.view.cullface_back = GL_BACK;
6087 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6089 r_refdef.view.usecustompvs = true;
6091 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6093 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6096 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6097 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6098 GL_ScissorTest(false);
6099 R_ClearScreen(r_refdef.fogenabled);
6100 GL_ScissorTest(true);
6101 if(r_water_scissormode.integer & 2)
6102 R_View_UpdateWithScissor(myscissor);
6105 R_AnimCache_CacheVisibleEntities();
6106 if(r_water_scissormode.integer & 1)
6107 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6108 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6110 r_fb.water.hideplayer = false;
6111 p->rt_reflection = rt;
6114 // render the normal view scene and copy into texture
6115 // (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)
6116 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6118 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6119 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6121 r_refdef.view = myview;
6122 if(r_water_scissormode.integer)
6124 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6125 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6127 p->rt_reflection = NULL;
6128 p->rt_refraction = NULL;
6129 p->rt_camera = NULL;
6134 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6136 r_refdef.view.clipplane = p->plane;
6137 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6138 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6140 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6142 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6143 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6144 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6145 R_RenderView_UpdateViewVectors();
6146 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6148 r_refdef.view.usecustompvs = true;
6149 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);
6153 PlaneClassify(&r_refdef.view.clipplane);
6155 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6156 GL_ScissorTest(false);
6157 R_ClearScreen(r_refdef.fogenabled);
6158 GL_ScissorTest(true);
6159 if(r_water_scissormode.integer & 2)
6160 R_View_UpdateWithScissor(myscissor);
6163 R_AnimCache_CacheVisibleEntities();
6164 if(r_water_scissormode.integer & 1)
6165 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6166 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6168 r_fb.water.hideplayer = false;
6169 p->rt_refraction = rt;
6171 else if (p->materialflags & MATERIALFLAG_CAMERA)
6173 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6174 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6176 r_refdef.view = myview;
6178 r_refdef.view.clipplane = p->plane;
6179 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6180 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6182 r_refdef.view.width = r_fb.water.camerawidth;
6183 r_refdef.view.height = r_fb.water.cameraheight;
6184 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6185 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6186 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6187 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6189 if(p->camera_entity)
6191 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6192 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6195 // note: all of the view is used for displaying... so
6196 // there is no use in scissoring
6198 // reverse the cullface settings for this render
6199 r_refdef.view.cullface_front = GL_FRONT;
6200 r_refdef.view.cullface_back = GL_BACK;
6201 // also reverse the view matrix
6202 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
6203 R_RenderView_UpdateViewVectors();
6204 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6206 r_refdef.view.usecustompvs = true;
6207 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);
6210 // camera needs no clipplane
6211 r_refdef.view.useclipplane = false;
6212 // TODO: is the camera origin always valid? if so we don't need to clear this
6213 r_refdef.view.usevieworiginculling = false;
6215 PlaneClassify(&r_refdef.view.clipplane);
6217 r_fb.water.hideplayer = false;
6219 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6220 GL_ScissorTest(false);
6221 R_ClearScreen(r_refdef.fogenabled);
6222 GL_ScissorTest(true);
6224 R_AnimCache_CacheVisibleEntities();
6225 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6227 r_fb.water.hideplayer = false;
6232 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6233 r_fb.water.renderingscene = false;
6234 r_refdef.view = originalview;
6235 R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
6237 R_AnimCache_CacheVisibleEntities();
6240 r_refdef.view = originalview;
6241 r_fb.water.renderingscene = false;
6242 Cvar_SetValueQuick(&r_water, 0);
6243 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6245 // lowquality hack, restore cvars
6246 if (qualityreduction > 0)
6248 if (qualityreduction >= 1)
6250 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6251 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6252 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6254 if (qualityreduction >= 2)
6256 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6257 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6258 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6263 static void R_Bloom_StartFrame(void)
6265 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6266 int viewwidth, viewheight;
6267 textype_t textype = TEXTYPE_COLORBUFFER;
6269 // clear the pointers to rendertargets from last frame as they're stale
6270 r_fb.rt_screen = NULL;
6271 r_fb.rt_bloom = NULL;
6273 switch (vid.renderpath)
6275 case RENDERPATH_GL20:
6276 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6277 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6278 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6279 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
6280 if (!vid.support.ext_framebuffer_object)
6283 case RENDERPATH_GL11:
6284 case RENDERPATH_GL13:
6285 case RENDERPATH_GLES1:
6286 return; // don't bother
6287 case RENDERPATH_GLES2:
6288 case RENDERPATH_D3D9:
6289 case RENDERPATH_D3D10:
6290 case RENDERPATH_D3D11:
6291 r_fb.usedepthtextures = false;
6293 case RENDERPATH_SOFT:
6294 r_fb.usedepthtextures = true;
6298 if (r_viewscale_fpsscaling.integer)
6300 double actualframetime;
6301 double targetframetime;
6303 actualframetime = r_refdef.lastdrawscreentime;
6304 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6305 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6306 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6307 if (r_viewscale_fpsscaling_stepsize.value > 0)
6308 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6309 viewscalefpsadjusted += adjust;
6310 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6313 viewscalefpsadjusted = 1.0f;
6315 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6317 // set bloomwidth and bloomheight to the bloom resolution that will be
6318 // used (often less than the screen resolution for faster rendering)
6319 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6320 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6321 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6322 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6323 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6325 // calculate desired texture sizes
6326 screentexturewidth = viewwidth;
6327 screentextureheight = viewheight;
6328 bloomtexturewidth = r_fb.bloomwidth;
6329 bloomtextureheight = r_fb.bloomheight;
6331 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))
6333 Cvar_SetValueQuick(&r_bloom, 0);
6334 Cvar_SetValueQuick(&r_motionblur, 0);
6335 Cvar_SetValueQuick(&r_damageblur, 0);
6338 // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
6339 if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
6341 if (r_fb.ghosttexture)
6342 R_FreeTexture(r_fb.ghosttexture);
6343 r_fb.ghosttexture = NULL;
6345 r_fb.screentexturewidth = screentexturewidth;
6346 r_fb.screentextureheight = screentextureheight;
6347 r_fb.textype = textype;
6349 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6351 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6352 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);
6353 r_fb.ghosttexture_valid = false;
6357 if (r_bloom.integer)
6359 // bloom texture is a different resolution
6360 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6361 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6362 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6365 r_fb.bloomwidth = r_fb.bloomheight = 0;
6367 r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6369 r_refdef.view.clear = true;
6372 static void R_Bloom_MakeTexture(void)
6375 float xoffset, yoffset, r, brighten;
6376 float colorscale = r_bloom_colorscale.value;
6377 r_viewport_t bloomviewport;
6378 r_rendertarget_t *prev, *cur;
6379 textype_t textype = r_fb.rt_screen->colortextype[0];
6381 r_refdef.stats[r_stat_bloom]++;
6383 R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6385 // scale down screen texture to the bloom texture size
6387 prev = r_fb.rt_screen;
6388 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6389 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6390 R_SetViewport(&bloomviewport);
6391 GL_CullFace(GL_NONE);
6392 GL_DepthTest(false);
6393 GL_BlendFunc(GL_ONE, GL_ZERO);
6394 GL_Color(colorscale, colorscale, colorscale, 1);
6395 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6396 // TODO: do boxfilter scale-down in shader?
6397 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
6398 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6399 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6400 // we now have a properly scaled bloom image
6402 // multiply bloom image by itself as many times as desired to darken it
6403 // TODO: if people actually use this it could be done more quickly in the previous shader pass
6404 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6407 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6408 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6410 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6412 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6413 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6414 GL_Color(1,1,1,1); // no fix factor supported here
6415 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6416 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6417 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6418 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6421 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6422 brighten = r_bloom_brighten.value;
6423 brighten = sqrt(brighten);
6425 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6427 for (dir = 0;dir < 2;dir++)
6430 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6431 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6432 // blend on at multiple vertical offsets to achieve a vertical blur
6433 // TODO: do offset blends using GLSL
6434 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6435 GL_BlendFunc(GL_ONE, GL_ZERO);
6436 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6437 for (x = -range;x <= range;x++)
6439 if (!dir){xoffset = 0;yoffset = x;}
6440 else {xoffset = x;yoffset = 0;}
6441 xoffset /= (float)prev->texturewidth;
6442 yoffset /= (float)prev->textureheight;
6443 // compute a texcoord array with the specified x and y offset
6444 r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
6445 r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
6446 r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
6447 r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
6448 r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
6449 r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
6450 r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
6451 r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
6452 // this r value looks like a 'dot' particle, fading sharply to
6453 // black at the edges
6454 // (probably not realistic but looks good enough)
6455 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6456 //r = brighten/(range*2+1);
6457 r = brighten / (range * 2 + 1);
6459 r *= (1 - x*x/(float)((range+1)*(range+1)));
6462 GL_Color(r, r, r, 1);
6463 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6464 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6465 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6466 GL_BlendFunc(GL_ONE, GL_ONE);
6470 // now we have the bloom image, so keep track of it
6471 r_fb.rt_bloom = cur;
6474 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6476 dpuint64 permutation;
6477 float uservecs[4][4];
6478 rtexture_t *viewtexture;
6479 rtexture_t *bloomtexture;
6481 R_EntityMatrix(&identitymatrix);
6483 switch (vid.renderpath)
6485 case RENDERPATH_GL20:
6486 case RENDERPATH_D3D9:
6487 case RENDERPATH_D3D10:
6488 case RENDERPATH_D3D11:
6489 case RENDERPATH_SOFT:
6490 case RENDERPATH_GLES2:
6492 (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
6493 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6494 | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6495 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6496 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6498 if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6500 // declare variables
6501 float blur_factor, blur_mouseaccel, blur_velocity;
6502 static float blur_average;
6503 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6505 // set a goal for the factoring
6506 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6507 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6508 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6509 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6510 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6511 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6513 // from the goal, pick an averaged value between goal and last value
6514 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6515 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6517 // enforce minimum amount of blur
6518 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6520 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6522 // calculate values into a standard alpha
6523 cl.motionbluralpha = 1 - exp(-
6525 (r_motionblur.value * blur_factor / 80)
6527 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6530 max(0.0001, cl.time - cl.oldtime) // fps independent
6533 // randomization for the blur value to combat persistent ghosting
6534 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6535 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6538 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6539 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6541 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6542 GL_Color(1, 1, 1, cl.motionbluralpha);
6543 R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
6544 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
6545 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6546 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547 r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
6550 // updates old view angles for next pass
6551 VectorCopy(cl.viewangles, blur_oldangles);
6553 // copy view into the ghost texture
6554 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
6555 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
6556 r_fb.ghosttexture_valid = true;
6559 if (r_fb.bloomwidth)
6561 // make the bloom texture
6562 R_Bloom_MakeTexture();
6565 #if _MSC_VER >= 1400
6566 #define sscanf sscanf_s
6568 memset(uservecs, 0, sizeof(uservecs));
6569 if (r_glsl_postprocess_uservec1_enable.integer)
6570 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6571 if (r_glsl_postprocess_uservec2_enable.integer)
6572 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6573 if (r_glsl_postprocess_uservec3_enable.integer)
6574 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6575 if (r_glsl_postprocess_uservec4_enable.integer)
6576 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6578 // render to the screen fbo
6579 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6580 GL_Color(1, 1, 1, 1);
6581 GL_BlendFunc(GL_ONE, GL_ZERO);
6583 viewtexture = r_fb.rt_screen->colortexture[0];
6584 bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
6586 if (r_rendertarget_debug.integer >= 0)
6588 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
6589 if (rt && rt->colortexture[0])
6591 viewtexture = rt->colortexture[0];
6592 bloomtexture = NULL;
6596 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
6597 switch(vid.renderpath)
6599 case RENDERPATH_GL20:
6600 case RENDERPATH_GLES2:
6601 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6602 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , viewtexture);
6603 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , bloomtexture);
6604 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6605 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]);
6606 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6607 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]);
6608 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]);
6609 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]);
6610 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]);
6611 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6612 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6613 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);
6615 case RENDERPATH_D3D9:
6617 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6618 R_Mesh_TexBind(GL20TU_FIRST , viewtexture);
6619 R_Mesh_TexBind(GL20TU_SECOND , bloomtexture);
6620 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6621 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6622 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6623 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6624 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6625 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6626 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6627 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6628 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6629 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6632 case RENDERPATH_D3D10:
6633 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6635 case RENDERPATH_D3D11:
6636 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6638 case RENDERPATH_SOFT:
6639 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6640 R_Mesh_TexBind(GL20TU_FIRST , viewtexture);
6641 R_Mesh_TexBind(GL20TU_SECOND , bloomtexture);
6642 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6643 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6644 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6645 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6646 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6647 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6648 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6649 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6650 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6651 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6656 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6657 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6659 case RENDERPATH_GL11:
6660 case RENDERPATH_GL13:
6661 case RENDERPATH_GLES1:
6662 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6664 // apply a color tint to the whole view
6665 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6666 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6667 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6668 R_SetupShader_Generic_NoTexture(false, true);
6669 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6670 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6676 matrix4x4_t r_waterscrollmatrix;
6678 void R_UpdateFog(void)
6681 if (gamemode == GAME_NEHAHRA)
6683 if (gl_fogenable.integer)
6685 r_refdef.oldgl_fogenable = true;
6686 r_refdef.fog_density = gl_fogdensity.value;
6687 r_refdef.fog_red = gl_fogred.value;
6688 r_refdef.fog_green = gl_foggreen.value;
6689 r_refdef.fog_blue = gl_fogblue.value;
6690 r_refdef.fog_alpha = 1;
6691 r_refdef.fog_start = 0;
6692 r_refdef.fog_end = gl_skyclip.value;
6693 r_refdef.fog_height = 1<<30;
6694 r_refdef.fog_fadedepth = 128;
6696 else if (r_refdef.oldgl_fogenable)
6698 r_refdef.oldgl_fogenable = false;
6699 r_refdef.fog_density = 0;
6700 r_refdef.fog_red = 0;
6701 r_refdef.fog_green = 0;
6702 r_refdef.fog_blue = 0;
6703 r_refdef.fog_alpha = 0;
6704 r_refdef.fog_start = 0;
6705 r_refdef.fog_end = 0;
6706 r_refdef.fog_height = 1<<30;
6707 r_refdef.fog_fadedepth = 128;
6712 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6713 r_refdef.fog_start = max(0, r_refdef.fog_start);
6714 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6716 if (r_refdef.fog_density && r_drawfog.integer)
6718 r_refdef.fogenabled = true;
6719 // this is the point where the fog reaches 0.9986 alpha, which we
6720 // consider a good enough cutoff point for the texture
6721 // (0.9986 * 256 == 255.6)
6722 if (r_fog_exp2.integer)
6723 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6725 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6726 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6727 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6728 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6729 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6730 R_BuildFogHeightTexture();
6731 // fog color was already set
6732 // update the fog texture
6733 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)
6734 R_BuildFogTexture();
6735 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6736 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6739 r_refdef.fogenabled = false;
6742 if (r_refdef.fog_density)
6744 r_refdef.fogcolor[0] = r_refdef.fog_red;
6745 r_refdef.fogcolor[1] = r_refdef.fog_green;
6746 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6748 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6749 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6750 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6751 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6755 VectorCopy(r_refdef.fogcolor, fogvec);
6756 // color.rgb *= ContrastBoost * SceneBrightness;
6757 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6758 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6759 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6760 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6765 void R_UpdateVariables(void)
6769 r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6771 r_refdef.farclip = r_farclip_base.value;
6772 if (r_refdef.scene.worldmodel)
6773 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6774 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6776 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6777 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6778 r_refdef.polygonfactor = 0;
6779 r_refdef.polygonoffset = 0;
6780 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6781 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6783 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6784 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6785 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6786 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6787 r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6788 if (FAKELIGHT_ENABLED)
6790 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6792 else if (r_refdef.scene.worldmodel)
6794 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6796 if (r_showsurfaces.integer)
6798 r_refdef.scene.rtworld = false;
6799 r_refdef.scene.rtworldshadows = false;
6800 r_refdef.scene.rtdlight = false;
6801 r_refdef.scene.rtdlightshadows = false;
6802 r_refdef.scene.lightmapintensity = 0;
6805 r_gpuskeletal = false;
6806 switch(vid.renderpath)
6808 case RENDERPATH_GL20:
6809 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6810 case RENDERPATH_D3D9:
6811 case RENDERPATH_D3D10:
6812 case RENDERPATH_D3D11:
6813 case RENDERPATH_SOFT:
6814 case RENDERPATH_GLES2:
6815 if(!vid_gammatables_trivial)
6817 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6819 // build GLSL gamma texture
6820 #define RAMPWIDTH 256
6821 unsigned short ramp[RAMPWIDTH * 3];
6822 unsigned char rampbgr[RAMPWIDTH][4];
6825 r_texture_gammaramps_serial = vid_gammatables_serial;
6827 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6828 for(i = 0; i < RAMPWIDTH; ++i)
6830 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6831 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6832 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6835 if (r_texture_gammaramps)
6837 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6841 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6847 // remove GLSL gamma texture
6850 case RENDERPATH_GL11:
6851 case RENDERPATH_GL13:
6852 case RENDERPATH_GLES1:
6857 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6858 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6864 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6865 if( scenetype != r_currentscenetype ) {
6866 // store the old scenetype
6867 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6868 r_currentscenetype = scenetype;
6869 // move in the new scene
6870 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6879 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6881 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6882 if( scenetype == r_currentscenetype ) {
6883 return &r_refdef.scene;
6885 return &r_scenes_store[ scenetype ];
6889 static int R_SortEntities_Compare(const void *ap, const void *bp)
6891 const entity_render_t *a = *(const entity_render_t **)ap;
6892 const entity_render_t *b = *(const entity_render_t **)bp;
6895 if(a->model < b->model)
6897 if(a->model > b->model)
6901 // TODO possibly calculate the REAL skinnum here first using
6903 if(a->skinnum < b->skinnum)
6905 if(a->skinnum > b->skinnum)
6908 // everything we compared is equal
6911 static void R_SortEntities(void)
6913 // below or equal 2 ents, sorting never gains anything
6914 if(r_refdef.scene.numentities <= 2)
6917 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6925 int dpsoftrast_test;
6926 extern cvar_t r_shadow_bouncegrid;
6927 extern cvar_t v_isometric;
6928 extern void V_MakeViewIsometric(void);
6929 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
6931 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6933 rtexture_t *viewdepthtexture = NULL;
6934 rtexture_t *viewcolortexture = NULL;
6935 int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
6937 // finish any 2D rendering that was queued
6940 dpsoftrast_test = r_test.integer;
6942 if (r_timereport_active)
6943 R_TimeReport("start");
6944 r_textureframe++; // used only by R_GetCurrentTexture
6945 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
6947 if(R_CompileShader_CheckStaticParms())
6950 if (!r_drawentities.integer)
6951 r_refdef.scene.numentities = 0;
6952 else if (r_sortentities.integer)
6955 R_AnimCache_ClearCache();
6957 /* adjust for stereo display */
6958 if(R_Stereo_Active())
6960 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);
6961 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6964 if (r_refdef.view.isoverlay)
6966 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6967 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6968 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6969 R_TimeReport("depthclear");
6971 r_refdef.view.showdebug = false;
6973 r_fb.water.enabled = false;
6974 r_fb.water.numwaterplanes = 0;
6976 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
6978 r_refdef.view.matrix = originalmatrix;
6984 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6986 r_refdef.view.matrix = originalmatrix;
6990 r_refdef.view.usevieworiginculling = !r_trippy.value && r_refdef.view.useperspective;
6991 if (v_isometric.integer && r_refdef.view.ismain)
6992 V_MakeViewIsometric();
6994 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6996 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6997 // in sRGB fallback, behave similar to true sRGB: convert this
6998 // value from linear to sRGB
6999 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7001 R_RenderView_UpdateViewVectors();
7003 R_Shadow_UpdateWorldLightSelection();
7005 // this will set up r_fb.rt_screen
7006 R_Bloom_StartFrame();
7008 // apply bloom brightness offset
7010 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7012 // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
7015 viewfbo = r_fb.rt_screen->fbo;
7016 viewdepthtexture = r_fb.rt_screen->depthtexture;
7017 viewcolortexture = r_fb.rt_screen->colortexture[0];
7021 viewheight = height;
7024 R_Water_StartFrame();
7027 if (r_timereport_active)
7028 R_TimeReport("viewsetup");
7030 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7032 // clear the whole fbo every frame - otherwise the driver will consider
7033 // it to be an inter-frame texture and stall in multi-gpu configurations
7035 GL_ScissorTest(false);
7036 R_ClearScreen(r_refdef.fogenabled);
7037 if (r_timereport_active)
7038 R_TimeReport("viewclear");
7040 r_refdef.view.clear = true;
7042 r_refdef.view.showdebug = true;
7045 if (r_timereport_active)
7046 R_TimeReport("visibility");
7048 R_AnimCache_CacheVisibleEntities();
7049 if (r_timereport_active)
7050 R_TimeReport("animcache");
7052 R_Shadow_UpdateBounceGridTexture();
7053 if (r_timereport_active && r_shadow_bouncegrid.integer)
7054 R_TimeReport("bouncegrid");
7056 r_fb.water.numwaterplanes = 0;
7057 if (r_fb.water.enabled)
7058 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7060 // for the actual view render we use scissoring a fair amount, so scissor
7061 // test needs to be on
7063 GL_ScissorTest(true);
7064 GL_Scissor(viewx, viewy, viewwidth, viewheight);
7065 R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7066 r_fb.water.numwaterplanes = 0;
7068 // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7069 GL_ScissorTest(false);
7071 R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7072 if (r_timereport_active)
7073 R_TimeReport("blendview");
7075 r_refdef.view.matrix = originalmatrix;
7079 // go back to 2d rendering
7083 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7085 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7087 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7088 if (r_timereport_active)
7089 R_TimeReport("waterworld");
7092 // don't let sound skip if going slow
7093 if (r_refdef.scene.extraupdate)
7096 R_DrawModelsAddWaterPlanes();
7097 if (r_timereport_active)
7098 R_TimeReport("watermodels");
7100 if (r_fb.water.numwaterplanes)
7102 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7103 if (r_timereport_active)
7104 R_TimeReport("waterscenes");
7108 extern cvar_t cl_locs_show;
7109 static void R_DrawLocs(void);
7110 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7111 static void R_DrawModelDecals(void);
7112 extern cvar_t cl_decals_newsystem;
7113 extern qboolean r_shadow_usingdeferredprepass;
7114 extern int r_shadow_shadowmapatlas_modelshadows_size;
7115 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7117 qboolean shadowmapping = false;
7119 if (r_timereport_active)
7120 R_TimeReport("beginscene");
7122 r_refdef.stats[r_stat_renders]++;
7126 // don't let sound skip if going slow
7127 if (r_refdef.scene.extraupdate)
7130 R_MeshQueue_BeginScene();
7134 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);
7136 if (r_timereport_active)
7137 R_TimeReport("skystartframe");
7139 if (cl.csqc_vidvars.drawworld)
7141 // don't let sound skip if going slow
7142 if (r_refdef.scene.extraupdate)
7145 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7147 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7148 if (r_timereport_active)
7149 R_TimeReport("worldsky");
7152 if (R_DrawBrushModelsSky() && r_timereport_active)
7153 R_TimeReport("bmodelsky");
7155 if (skyrendermasked && skyrenderlater)
7157 // we have to force off the water clipping plane while rendering sky
7158 R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7160 R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7161 if (r_timereport_active)
7162 R_TimeReport("sky");
7166 // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7167 r_shadow_viewfbo = viewfbo;
7168 r_shadow_viewdepthtexture = viewdepthtexture;
7169 r_shadow_viewcolortexture = viewcolortexture;
7170 r_shadow_viewx = viewx;
7171 r_shadow_viewy = viewy;
7172 r_shadow_viewwidth = viewwidth;
7173 r_shadow_viewheight = viewheight;
7175 R_Shadow_PrepareModelShadows();
7176 R_Shadow_PrepareLights();
7177 if (r_timereport_active)
7178 R_TimeReport("preparelights");
7180 // render all the shadowmaps that will be used for this view
7181 shadowmapping = R_Shadow_ShadowMappingEnabled();
7182 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7184 R_Shadow_DrawShadowMaps();
7185 if (r_timereport_active)
7186 R_TimeReport("shadowmaps");
7189 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7190 if (r_shadow_usingdeferredprepass)
7191 R_Shadow_DrawPrepass();
7193 // now we begin the forward pass of the view render
7194 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7196 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7197 if (r_timereport_active)
7198 R_TimeReport("worlddepth");
7200 if (r_depthfirst.integer >= 2)
7202 R_DrawModelsDepth();
7203 if (r_timereport_active)
7204 R_TimeReport("modeldepth");
7207 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7209 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7210 if (r_timereport_active)
7211 R_TimeReport("world");
7214 // don't let sound skip if going slow
7215 if (r_refdef.scene.extraupdate)
7219 if (r_timereport_active)
7220 R_TimeReport("models");
7222 // don't let sound skip if going slow
7223 if (r_refdef.scene.extraupdate)
7226 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7228 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7229 R_Shadow_DrawModelShadows();
7230 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7231 // don't let sound skip if going slow
7232 if (r_refdef.scene.extraupdate)
7236 if (!r_shadow_usingdeferredprepass)
7238 R_Shadow_DrawLights();
7239 if (r_timereport_active)
7240 R_TimeReport("rtlights");
7243 // don't let sound skip if going slow
7244 if (r_refdef.scene.extraupdate)
7247 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7249 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7250 R_Shadow_DrawModelShadows();
7251 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7252 // don't let sound skip if going slow
7253 if (r_refdef.scene.extraupdate)
7257 if (cl.csqc_vidvars.drawworld)
7259 if (cl_decals_newsystem.integer)
7261 R_DrawModelDecals();
7262 if (r_timereport_active)
7263 R_TimeReport("modeldecals");
7268 if (r_timereport_active)
7269 R_TimeReport("decals");
7273 if (r_timereport_active)
7274 R_TimeReport("particles");
7277 if (r_timereport_active)
7278 R_TimeReport("explosions");
7281 if (r_refdef.view.showdebug)
7283 if (cl_locs_show.integer)
7286 if (r_timereport_active)
7287 R_TimeReport("showlocs");
7290 if (r_drawportals.integer)
7293 if (r_timereport_active)
7294 R_TimeReport("portals");
7297 if (r_showbboxes_client.value > 0)
7299 R_DrawEntityBBoxes(CLVM_prog);
7300 if (r_timereport_active)
7301 R_TimeReport("clbboxes");
7303 if (r_showbboxes.value > 0)
7305 R_DrawEntityBBoxes(SVVM_prog);
7306 if (r_timereport_active)
7307 R_TimeReport("svbboxes");
7311 if (r_transparent.integer)
7313 R_MeshQueue_RenderTransparent();
7314 if (r_timereport_active)
7315 R_TimeReport("drawtrans");
7318 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))
7320 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7321 if (r_timereport_active)
7322 R_TimeReport("worlddebug");
7323 R_DrawModelsDebug();
7324 if (r_timereport_active)
7325 R_TimeReport("modeldebug");
7328 if (cl.csqc_vidvars.drawworld)
7330 R_Shadow_DrawCoronas();
7331 if (r_timereport_active)
7332 R_TimeReport("coronas");
7337 GL_DepthTest(false);
7338 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7339 GL_Color(1, 1, 1, 1);
7340 qglBegin(GL_POLYGON);
7341 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7342 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7343 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7344 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7346 qglBegin(GL_POLYGON);
7347 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]);
7348 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]);
7349 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]);
7350 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]);
7352 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7356 // don't let sound skip if going slow
7357 if (r_refdef.scene.extraupdate)
7361 static const unsigned short bboxelements[36] =
7371 #define BBOXEDGES 13
7372 static const float bboxedges[BBOXEDGES][6] =
7375 { 0, 0, 0, 1, 1, 1 },
7377 { 0, 0, 0, 0, 1, 0 },
7378 { 0, 0, 0, 1, 0, 0 },
7379 { 0, 1, 0, 1, 1, 0 },
7380 { 1, 0, 0, 1, 1, 0 },
7382 { 0, 0, 1, 0, 1, 1 },
7383 { 0, 0, 1, 1, 0, 1 },
7384 { 0, 1, 1, 1, 1, 1 },
7385 { 1, 0, 1, 1, 1, 1 },
7387 { 0, 0, 0, 0, 0, 1 },
7388 { 1, 0, 0, 1, 0, 1 },
7389 { 0, 1, 0, 0, 1, 1 },
7390 { 1, 1, 0, 1, 1, 1 },
7393 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7395 int numvertices = BBOXEDGES * 8;
7396 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7397 int numtriangles = BBOXEDGES * 12;
7398 unsigned short elements[BBOXEDGES * 36];
7400 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7402 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7404 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7405 GL_DepthMask(false);
7406 GL_DepthRange(0, 1);
7407 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7409 for (edge = 0; edge < BBOXEDGES; edge++)
7411 for (i = 0; i < 3; i++)
7413 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7414 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7416 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7417 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7418 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7419 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7420 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7421 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7422 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7423 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7424 for (i = 0; i < 36; i++)
7425 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7427 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7428 if (r_refdef.fogenabled)
7430 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7432 f1 = RSurf_FogVertex(v);
7434 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7435 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7436 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7439 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7440 R_Mesh_ResetTextureState();
7441 R_SetupShader_Generic_NoTexture(false, false);
7442 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7445 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7447 // hacky overloading of the parameters
7448 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7451 prvm_edict_t *edict;
7453 GL_CullFace(GL_NONE);
7454 R_SetupShader_Generic_NoTexture(false, false);
7456 for (i = 0;i < numsurfaces;i++)
7458 edict = PRVM_EDICT_NUM(surfacelist[i]);
7459 switch ((int)PRVM_serveredictfloat(edict, solid))
7461 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7462 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7463 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7464 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7465 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7466 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7467 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7469 if (prog == CLVM_prog)
7470 color[3] *= r_showbboxes_client.value;
7472 color[3] *= r_showbboxes.value;
7473 color[3] = bound(0, color[3], 1);
7474 GL_DepthTest(!r_showdisabledepthtest.integer);
7475 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7479 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7482 prvm_edict_t *edict;
7488 for (i = 0; i < prog->num_edicts; i++)
7490 edict = PRVM_EDICT_NUM(i);
7491 if (edict->priv.server->free)
7493 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7494 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7496 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7498 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7499 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7503 static const int nomodelelement3i[24] =
7515 static const unsigned short nomodelelement3s[24] =
7527 static const float nomodelvertex3f[6*3] =
7537 static const float nomodelcolor4f[6*4] =
7539 0.0f, 0.0f, 0.5f, 1.0f,
7540 0.0f, 0.0f, 0.5f, 1.0f,
7541 0.0f, 0.5f, 0.0f, 1.0f,
7542 0.0f, 0.5f, 0.0f, 1.0f,
7543 0.5f, 0.0f, 0.0f, 1.0f,
7544 0.5f, 0.0f, 0.0f, 1.0f
7547 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7553 RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7555 // this is only called once per entity so numsurfaces is always 1, and
7556 // surfacelist is always {0}, so this code does not handle batches
7558 if (rsurface.ent_flags & RENDER_ADDITIVE)
7560 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7561 GL_DepthMask(false);
7563 else if (ent->alpha < 1)
7565 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7566 GL_DepthMask(false);
7570 GL_BlendFunc(GL_ONE, GL_ZERO);
7573 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7574 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7575 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7576 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7577 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7578 for (i = 0, c = color4f;i < 6;i++, c += 4)
7580 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7581 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7582 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7585 if (r_refdef.fogenabled)
7587 for (i = 0, c = color4f;i < 6;i++, c += 4)
7589 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7591 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7592 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7593 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7596 // R_Mesh_ResetTextureState();
7597 R_SetupShader_Generic_NoTexture(false, false);
7598 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7599 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7602 void R_DrawNoModel(entity_render_t *ent)
7605 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7606 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7607 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7609 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7612 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7614 vec3_t right1, right2, diff, normal;
7616 VectorSubtract (org2, org1, normal);
7618 // calculate 'right' vector for start
7619 VectorSubtract (r_refdef.view.origin, org1, diff);
7620 CrossProduct (normal, diff, right1);
7621 VectorNormalize (right1);
7623 // calculate 'right' vector for end
7624 VectorSubtract (r_refdef.view.origin, org2, diff);
7625 CrossProduct (normal, diff, right2);
7626 VectorNormalize (right2);
7628 vert[ 0] = org1[0] + width * right1[0];
7629 vert[ 1] = org1[1] + width * right1[1];
7630 vert[ 2] = org1[2] + width * right1[2];
7631 vert[ 3] = org1[0] - width * right1[0];
7632 vert[ 4] = org1[1] - width * right1[1];
7633 vert[ 5] = org1[2] - width * right1[2];
7634 vert[ 6] = org2[0] - width * right2[0];
7635 vert[ 7] = org2[1] - width * right2[1];
7636 vert[ 8] = org2[2] - width * right2[2];
7637 vert[ 9] = org2[0] + width * right2[0];
7638 vert[10] = org2[1] + width * right2[1];
7639 vert[11] = org2[2] + width * right2[2];
7642 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7644 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7645 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7646 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7647 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7648 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7649 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7650 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7651 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7652 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7653 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7654 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7655 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7658 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7663 VectorSet(v, x, y, z);
7664 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7665 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7667 if (i == mesh->numvertices)
7669 if (mesh->numvertices < mesh->maxvertices)
7671 VectorCopy(v, vertex3f);
7672 mesh->numvertices++;
7674 return mesh->numvertices;
7680 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7684 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7685 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7686 e = mesh->element3i + mesh->numtriangles * 3;
7687 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7689 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7690 if (mesh->numtriangles < mesh->maxtriangles)
7695 mesh->numtriangles++;
7697 element[1] = element[2];
7701 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7705 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7706 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7707 e = mesh->element3i + mesh->numtriangles * 3;
7708 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7710 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7711 if (mesh->numtriangles < mesh->maxtriangles)
7716 mesh->numtriangles++;
7718 element[1] = element[2];
7722 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7723 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7725 int planenum, planenum2;
7728 mplane_t *plane, *plane2;
7730 double temppoints[2][256*3];
7731 // figure out how large a bounding box we need to properly compute this brush
7733 for (w = 0;w < numplanes;w++)
7734 maxdist = max(maxdist, fabs(planes[w].dist));
7735 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7736 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7737 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7741 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7742 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7744 if (planenum2 == planenum)
7746 PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7749 if (tempnumpoints < 3)
7751 // generate elements forming a triangle fan for this polygon
7752 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7756 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7758 texturelayer_t *layer;
7759 layer = t->currentlayers + t->currentnumlayers++;
7761 layer->depthmask = depthmask;
7762 layer->blendfunc1 = blendfunc1;
7763 layer->blendfunc2 = blendfunc2;
7764 layer->texture = texture;
7765 layer->texmatrix = *matrix;
7766 layer->color[0] = r;
7767 layer->color[1] = g;
7768 layer->color[2] = b;
7769 layer->color[3] = a;
7772 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7774 if(parms[0] == 0 && parms[1] == 0)
7776 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7777 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7782 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7785 index = parms[2] + rsurface.shadertime * parms[3];
7786 index -= floor(index);
7787 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7790 case Q3WAVEFUNC_NONE:
7791 case Q3WAVEFUNC_NOISE:
7792 case Q3WAVEFUNC_COUNT:
7795 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7796 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7797 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7798 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7799 case Q3WAVEFUNC_TRIANGLE:
7801 f = index - floor(index);
7814 f = parms[0] + parms[1] * f;
7815 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7816 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7820 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7827 matrix4x4_t matrix, temp;
7828 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7829 // it's better to have one huge fixup every 9 hours than gradual
7830 // degradation over time which looks consistently bad after many hours.
7832 // tcmod scroll in particular suffers from this degradation which can't be
7833 // effectively worked around even with floor() tricks because we don't
7834 // know if tcmod scroll is the last tcmod being applied, and for clampmap
7835 // a workaround involving floor() would be incorrect anyway...
7836 shadertime = rsurface.shadertime;
7837 if (shadertime >= 32768.0f)
7838 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7839 switch(tcmod->tcmod)
7843 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7844 matrix = r_waterscrollmatrix;
7846 matrix = identitymatrix;
7848 case Q3TCMOD_ENTITYTRANSLATE:
7849 // this is used in Q3 to allow the gamecode to control texcoord
7850 // scrolling on the entity, which is not supported in darkplaces yet.
7851 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7853 case Q3TCMOD_ROTATE:
7854 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7855 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7856 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7859 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7861 case Q3TCMOD_SCROLL:
7862 // this particular tcmod is a "bug for bug" compatible one with regards to
7863 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7864 // specifically did the wrapping and so we must mimic that...
7865 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7866 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7867 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7869 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7870 w = (int) tcmod->parms[0];
7871 h = (int) tcmod->parms[1];
7872 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7874 idx = (int) floor(f * w * h);
7875 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7877 case Q3TCMOD_STRETCH:
7878 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7879 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7881 case Q3TCMOD_TRANSFORM:
7882 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7883 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7884 VectorSet(tcmat + 6, 0 , 0 , 1);
7885 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7886 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7888 case Q3TCMOD_TURBULENT:
7889 // this is handled in the RSurf_PrepareVertices function
7890 matrix = identitymatrix;
7894 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7897 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7899 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7900 char name[MAX_QPATH];
7901 skinframe_t *skinframe;
7902 unsigned char pixels[296*194];
7903 strlcpy(cache->name, skinname, sizeof(cache->name));
7904 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7905 if (developer_loading.integer)
7906 Con_Printf("loading %s\n", name);
7907 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7908 if (!skinframe || !skinframe->base)
7911 fs_offset_t filesize;
7913 f = FS_LoadFile(name, tempmempool, true, &filesize);
7916 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7917 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7921 cache->skinframe = skinframe;
7924 texture_t *R_GetCurrentTexture(texture_t *t)
7927 const entity_render_t *ent = rsurface.entity;
7928 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7929 q3shaderinfo_layer_tcmod_t *tcmod;
7930 float specularscale = 0.0f;
7932 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7933 return t->currentframe;
7934 t->update_lastrenderframe = r_textureframe;
7935 t->update_lastrenderentity = (void *)ent;
7937 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7938 t->camera_entity = ent->entitynumber;
7940 t->camera_entity = 0;
7942 // switch to an alternate material if this is a q1bsp animated material
7944 texture_t *texture = t;
7945 int s = rsurface.ent_skinnum;
7946 if ((unsigned int)s >= (unsigned int)model->numskins)
7948 if (model->skinscenes)
7950 if (model->skinscenes[s].framecount > 1)
7951 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7953 s = model->skinscenes[s].firstframe;
7956 t = t + s * model->num_surfaces;
7959 // use an alternate animation if the entity's frame is not 0,
7960 // and only if the texture has an alternate animation
7961 if (t->animated == 2) // q2bsp
7962 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
7963 else if (rsurface.ent_alttextures && t->anim_total[1])
7964 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7966 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7968 texture->currentframe = t;
7971 // update currentskinframe to be a qw skin or animation frame
7972 if (rsurface.ent_qwskin >= 0)
7974 i = rsurface.ent_qwskin;
7975 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7977 r_qwskincache_size = cl.maxclients;
7979 Mem_Free(r_qwskincache);
7980 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7982 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7983 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7984 t->currentskinframe = r_qwskincache[i].skinframe;
7985 if (t->materialshaderpass && t->currentskinframe == NULL)
7986 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7988 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
7989 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7990 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
7991 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
7993 t->currentmaterialflags = t->basematerialflags;
7994 t->currentalpha = rsurface.entity->alpha * t->basealpha;
7995 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7996 t->currentalpha *= r_wateralpha.value;
7997 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7998 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7999 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8000 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8002 // decide on which type of lighting to use for this surface
8003 if (rsurface.entity->render_modellight_forced)
8004 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8005 if (rsurface.entity->render_rtlight_disabled)
8006 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8007 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8009 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
8010 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
8011 for (q = 0; q < 3; q++)
8013 t->render_glowmod[q] = rsurface.entity->glowmod[q];
8014 t->render_modellight_lightdir[q] = q == 2;
8015 t->render_modellight_ambient[q] = 1;
8016 t->render_modellight_diffuse[q] = 0;
8017 t->render_modellight_specular[q] = 0;
8018 t->render_lightmap_ambient[q] = 0;
8019 t->render_lightmap_diffuse[q] = 0;
8020 t->render_lightmap_specular[q] = 0;
8021 t->render_rtlight_diffuse[q] = 0;
8022 t->render_rtlight_specular[q] = 0;
8025 else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8027 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8028 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8029 for (q = 0; q < 3; q++)
8031 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8032 t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8033 t->render_modellight_lightdir[q] = q == 2;
8034 t->render_modellight_diffuse[q] = 0;
8035 t->render_modellight_specular[q] = 0;
8036 t->render_lightmap_ambient[q] = 0;
8037 t->render_lightmap_diffuse[q] = 0;
8038 t->render_lightmap_specular[q] = 0;
8039 t->render_rtlight_diffuse[q] = 0;
8040 t->render_rtlight_specular[q] = 0;
8043 else if (FAKELIGHT_ENABLED)
8045 // no modellight if using fakelight for the map
8046 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8047 for (q = 0; q < 3; q++)
8049 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8050 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8051 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8052 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8053 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8054 t->render_lightmap_ambient[q] = 0;
8055 t->render_lightmap_diffuse[q] = 0;
8056 t->render_lightmap_specular[q] = 0;
8057 t->render_rtlight_diffuse[q] = 0;
8058 t->render_rtlight_specular[q] = 0;
8061 else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8063 // ambient + single direction light (modellight)
8064 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8065 for (q = 0; q < 3; q++)
8067 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8068 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8069 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8070 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8071 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8072 t->render_lightmap_ambient[q] = 0;
8073 t->render_lightmap_diffuse[q] = 0;
8074 t->render_lightmap_specular[q] = 0;
8075 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8076 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8081 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8082 for (q = 0; q < 3; q++)
8084 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8085 t->render_modellight_lightdir[q] = q == 2;
8086 t->render_modellight_ambient[q] = 0;
8087 t->render_modellight_diffuse[q] = 0;
8088 t->render_modellight_specular[q] = 0;
8089 t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8090 t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8091 t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8092 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8093 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8097 if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8099 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8100 // attribute, we punt it to the lightmap path and hope for the best,
8101 // but lighting doesn't work.
8103 // FIXME: this is fine for effects but CSQC polygons should be subject
8105 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8106 for (q = 0; q < 3; q++)
8108 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8109 t->render_modellight_lightdir[q] = q == 2;
8110 t->render_modellight_ambient[q] = 0;
8111 t->render_modellight_diffuse[q] = 0;
8112 t->render_modellight_specular[q] = 0;
8113 t->render_lightmap_ambient[q] = 0;
8114 t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8115 t->render_lightmap_specular[q] = 0;
8116 t->render_rtlight_diffuse[q] = 0;
8117 t->render_rtlight_specular[q] = 0;
8121 for (q = 0; q < 3; q++)
8123 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8124 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8127 if (rsurface.ent_flags & RENDER_ADDITIVE)
8128 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8129 else if (t->currentalpha < 1)
8130 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8131 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8132 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8133 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8134 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8135 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8136 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8137 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8138 if (t->backgroundshaderpass)
8139 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8140 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8142 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8143 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8146 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8147 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8149 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8150 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8152 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8153 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8155 // there is no tcmod
8156 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8158 t->currenttexmatrix = r_waterscrollmatrix;
8159 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8161 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8163 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8164 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8167 if (t->materialshaderpass)
8168 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8169 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8171 t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8172 if (t->currentskinframe->qpixels)
8173 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8174 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8175 if (!t->basetexture)
8176 t->basetexture = r_texture_notexture;
8177 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8178 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8179 t->nmaptexture = t->currentskinframe->nmap;
8180 if (!t->nmaptexture)
8181 t->nmaptexture = r_texture_blanknormalmap;
8182 t->glosstexture = r_texture_black;
8183 t->glowtexture = t->currentskinframe->glow;
8184 t->fogtexture = t->currentskinframe->fog;
8185 t->reflectmasktexture = t->currentskinframe->reflect;
8186 if (t->backgroundshaderpass)
8188 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8189 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8190 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8191 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8192 t->backgroundglosstexture = r_texture_black;
8193 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8194 if (!t->backgroundnmaptexture)
8195 t->backgroundnmaptexture = r_texture_blanknormalmap;
8196 // make sure that if glow is going to be used, both textures are not NULL
8197 if (!t->backgroundglowtexture && t->glowtexture)
8198 t->backgroundglowtexture = r_texture_black;
8199 if (!t->glowtexture && t->backgroundglowtexture)
8200 t->glowtexture = r_texture_black;
8204 t->backgroundbasetexture = r_texture_white;
8205 t->backgroundnmaptexture = r_texture_blanknormalmap;
8206 t->backgroundglosstexture = r_texture_black;
8207 t->backgroundglowtexture = NULL;
8209 t->specularpower = r_shadow_glossexponent.value;
8210 // TODO: store reference values for these in the texture?
8211 if (r_shadow_gloss.integer > 0)
8213 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8215 if (r_shadow_glossintensity.value > 0)
8217 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8218 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8219 specularscale = r_shadow_glossintensity.value;
8222 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8224 t->glosstexture = r_texture_white;
8225 t->backgroundglosstexture = r_texture_white;
8226 specularscale = r_shadow_gloss2intensity.value;
8227 t->specularpower = r_shadow_gloss2exponent.value;
8230 specularscale *= t->specularscalemod;
8231 t->specularpower *= t->specularpowermod;
8233 // lightmaps mode looks bad with dlights using actual texturing, so turn
8234 // off the colormap and glossmap, but leave the normalmap on as it still
8235 // accurately represents the shading involved
8236 if (gl_lightmaps.integer)
8238 t->basetexture = r_texture_grey128;
8239 t->pantstexture = r_texture_black;
8240 t->shirttexture = r_texture_black;
8241 if (gl_lightmaps.integer < 2)
8242 t->nmaptexture = r_texture_blanknormalmap;
8243 t->glosstexture = r_texture_black;
8244 t->glowtexture = NULL;
8245 t->fogtexture = NULL;
8246 t->reflectmasktexture = NULL;
8247 t->backgroundbasetexture = NULL;
8248 if (gl_lightmaps.integer < 2)
8249 t->backgroundnmaptexture = r_texture_blanknormalmap;
8250 t->backgroundglosstexture = r_texture_black;
8251 t->backgroundglowtexture = NULL;
8253 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8256 if (specularscale != 1.0f)
8258 for (q = 0; q < 3; q++)
8260 t->render_modellight_specular[q] *= specularscale;
8261 t->render_lightmap_specular[q] *= specularscale;
8262 t->render_rtlight_specular[q] *= specularscale;
8266 t->currentnumlayers = 0;
8267 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8269 int blendfunc1, blendfunc2;
8271 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8273 blendfunc1 = GL_SRC_ALPHA;
8274 blendfunc2 = GL_ONE;
8276 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8278 blendfunc1 = GL_SRC_ALPHA;
8279 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8281 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8283 blendfunc1 = t->customblendfunc[0];
8284 blendfunc2 = t->customblendfunc[1];
8288 blendfunc1 = GL_ONE;
8289 blendfunc2 = GL_ZERO;
8291 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8292 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8294 // basic lit geometry
8295 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
8296 // add pants/shirt if needed
8297 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8298 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, 2 * t->render_colormap_pants[0], 2 * t->render_colormap_pants[1], 2 * t->render_colormap_pants[2], t->currentalpha);
8299 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8300 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, 2 * t->render_colormap_shirt[0], 2 * t->render_colormap_shirt[1], 2 * t->render_colormap_shirt[2], t->currentalpha);
8304 // basic lit geometry
8305 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8306 // add pants/shirt if needed
8307 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8308 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8309 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8310 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8311 // now add ambient passes if needed
8312 if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8314 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8315 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8316 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8317 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8318 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8321 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8322 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8323 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8325 // if this is opaque use alpha blend which will darken the earlier
8328 // if this is an alpha blended material, all the earlier passes
8329 // were darkened by fog already, so we only need to add the fog
8330 // color ontop through the fog mask texture
8332 // if this is an additive blended material, all the earlier passes
8333 // were darkened by fog already, and we should not add fog color
8334 // (because the background was not darkened, there is no fog color
8335 // that was lost behind it).
8336 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->currentalpha);
8343 rsurfacestate_t rsurface;
8345 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8347 dp_model_t *model = ent->model;
8348 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8350 rsurface.entity = (entity_render_t *)ent;
8351 rsurface.skeleton = ent->skeleton;
8352 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8353 rsurface.ent_skinnum = ent->skinnum;
8354 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;
8355 rsurface.ent_flags = ent->flags;
8356 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8357 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8358 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8359 rsurface.matrix = ent->matrix;
8360 rsurface.inversematrix = ent->inversematrix;
8361 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8362 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8363 R_EntityMatrix(&rsurface.matrix);
8364 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8365 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8366 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8367 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8368 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8369 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8370 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8371 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8372 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8373 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8374 if (ent->model->brush.submodel && !prepass)
8376 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8377 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8379 // if the animcache code decided it should use the shader path, skip the deform step
8380 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8381 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8382 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8383 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8384 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8385 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8387 if (ent->animcache_vertex3f)
8389 r_refdef.stats[r_stat_batch_entitycache_count]++;
8390 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8391 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8392 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8393 rsurface.modelvertex3f = ent->animcache_vertex3f;
8394 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8395 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8396 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8397 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8398 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8399 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8400 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8401 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8402 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8403 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8404 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8405 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8406 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8407 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8409 else if (wanttangents)
8411 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8412 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8413 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8414 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8415 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8417 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8418 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8419 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8420 rsurface.modelvertexmesh = NULL;
8421 rsurface.modelvertexmesh_vertexbuffer = NULL;
8422 rsurface.modelvertexmesh_bufferoffset = 0;
8423 rsurface.modelvertex3f_vertexbuffer = NULL;
8424 rsurface.modelvertex3f_bufferoffset = 0;
8425 rsurface.modelvertex3f_vertexbuffer = 0;
8426 rsurface.modelvertex3f_bufferoffset = 0;
8427 rsurface.modelsvector3f_vertexbuffer = 0;
8428 rsurface.modelsvector3f_bufferoffset = 0;
8429 rsurface.modeltvector3f_vertexbuffer = 0;
8430 rsurface.modeltvector3f_bufferoffset = 0;
8431 rsurface.modelnormal3f_vertexbuffer = 0;
8432 rsurface.modelnormal3f_bufferoffset = 0;
8434 else if (wantnormals)
8436 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8437 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8438 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8439 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8440 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8441 rsurface.modelsvector3f = NULL;
8442 rsurface.modeltvector3f = NULL;
8443 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8444 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8445 rsurface.modelvertexmesh = NULL;
8446 rsurface.modelvertexmesh_vertexbuffer = NULL;
8447 rsurface.modelvertexmesh_bufferoffset = 0;
8448 rsurface.modelvertex3f_vertexbuffer = NULL;
8449 rsurface.modelvertex3f_bufferoffset = 0;
8450 rsurface.modelvertex3f_vertexbuffer = 0;
8451 rsurface.modelvertex3f_bufferoffset = 0;
8452 rsurface.modelsvector3f_vertexbuffer = 0;
8453 rsurface.modelsvector3f_bufferoffset = 0;
8454 rsurface.modeltvector3f_vertexbuffer = 0;
8455 rsurface.modeltvector3f_bufferoffset = 0;
8456 rsurface.modelnormal3f_vertexbuffer = 0;
8457 rsurface.modelnormal3f_bufferoffset = 0;
8461 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8462 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8463 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8464 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8465 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8466 rsurface.modelsvector3f = NULL;
8467 rsurface.modeltvector3f = NULL;
8468 rsurface.modelnormal3f = NULL;
8469 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8470 rsurface.modelvertexmesh = NULL;
8471 rsurface.modelvertexmesh_vertexbuffer = NULL;
8472 rsurface.modelvertexmesh_bufferoffset = 0;
8473 rsurface.modelvertex3f_vertexbuffer = NULL;
8474 rsurface.modelvertex3f_bufferoffset = 0;
8475 rsurface.modelvertex3f_vertexbuffer = 0;
8476 rsurface.modelvertex3f_bufferoffset = 0;
8477 rsurface.modelsvector3f_vertexbuffer = 0;
8478 rsurface.modelsvector3f_bufferoffset = 0;
8479 rsurface.modeltvector3f_vertexbuffer = 0;
8480 rsurface.modeltvector3f_bufferoffset = 0;
8481 rsurface.modelnormal3f_vertexbuffer = 0;
8482 rsurface.modelnormal3f_bufferoffset = 0;
8484 rsurface.modelgeneratedvertex = true;
8488 if (rsurface.entityskeletaltransform3x4)
8490 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8491 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8492 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8493 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8497 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8498 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8499 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8500 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8502 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8503 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8504 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8505 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8506 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8507 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8508 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8509 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8510 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8511 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8512 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8513 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8514 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8515 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8516 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8517 rsurface.modelgeneratedvertex = false;
8519 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8520 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8521 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8522 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8523 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8524 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8525 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8526 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8527 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8528 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8529 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8530 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8531 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8532 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8533 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8534 rsurface.modelelement3i = model->surfmesh.data_element3i;
8535 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8536 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8537 rsurface.modelelement3s = model->surfmesh.data_element3s;
8538 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8539 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8540 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8541 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8542 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8543 rsurface.modelsurfaces = model->data_surfaces;
8544 rsurface.batchgeneratedvertex = false;
8545 rsurface.batchfirstvertex = 0;
8546 rsurface.batchnumvertices = 0;
8547 rsurface.batchfirsttriangle = 0;
8548 rsurface.batchnumtriangles = 0;
8549 rsurface.batchvertex3f = NULL;
8550 rsurface.batchvertex3f_vertexbuffer = NULL;
8551 rsurface.batchvertex3f_bufferoffset = 0;
8552 rsurface.batchsvector3f = NULL;
8553 rsurface.batchsvector3f_vertexbuffer = NULL;
8554 rsurface.batchsvector3f_bufferoffset = 0;
8555 rsurface.batchtvector3f = NULL;
8556 rsurface.batchtvector3f_vertexbuffer = NULL;
8557 rsurface.batchtvector3f_bufferoffset = 0;
8558 rsurface.batchnormal3f = NULL;
8559 rsurface.batchnormal3f_vertexbuffer = NULL;
8560 rsurface.batchnormal3f_bufferoffset = 0;
8561 rsurface.batchlightmapcolor4f = NULL;
8562 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8563 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8564 rsurface.batchtexcoordtexture2f = NULL;
8565 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8566 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8567 rsurface.batchtexcoordlightmap2f = NULL;
8568 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8569 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8570 rsurface.batchskeletalindex4ub = NULL;
8571 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8572 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8573 rsurface.batchskeletalweight4ub = NULL;
8574 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8575 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8576 rsurface.batchvertexmesh = NULL;
8577 rsurface.batchvertexmesh_vertexbuffer = NULL;
8578 rsurface.batchvertexmesh_bufferoffset = 0;
8579 rsurface.batchelement3i = NULL;
8580 rsurface.batchelement3i_indexbuffer = NULL;
8581 rsurface.batchelement3i_bufferoffset = 0;
8582 rsurface.batchelement3s = NULL;
8583 rsurface.batchelement3s_indexbuffer = NULL;
8584 rsurface.batchelement3s_bufferoffset = 0;
8585 rsurface.passcolor4f = NULL;
8586 rsurface.passcolor4f_vertexbuffer = NULL;
8587 rsurface.passcolor4f_bufferoffset = 0;
8588 rsurface.forcecurrenttextureupdate = false;
8591 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)
8593 rsurface.entity = r_refdef.scene.worldentity;
8594 rsurface.skeleton = NULL;
8595 rsurface.ent_skinnum = 0;
8596 rsurface.ent_qwskin = -1;
8597 rsurface.ent_flags = entflags;
8598 rsurface.shadertime = r_refdef.scene.time - shadertime;
8599 rsurface.modelnumvertices = numvertices;
8600 rsurface.modelnumtriangles = numtriangles;
8601 rsurface.matrix = *matrix;
8602 rsurface.inversematrix = *inversematrix;
8603 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8604 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8605 R_EntityMatrix(&rsurface.matrix);
8606 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8607 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8608 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8609 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8610 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8611 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8612 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8613 rsurface.frameblend[0].lerp = 1;
8614 rsurface.ent_alttextures = false;
8615 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8616 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8617 rsurface.entityskeletaltransform3x4 = NULL;
8618 rsurface.entityskeletaltransform3x4buffer = NULL;
8619 rsurface.entityskeletaltransform3x4offset = 0;
8620 rsurface.entityskeletaltransform3x4size = 0;
8621 rsurface.entityskeletalnumtransforms = 0;
8622 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8623 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8624 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8625 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8628 rsurface.modelvertex3f = (float *)vertex3f;
8629 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8630 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8631 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8633 else if (wantnormals)
8635 rsurface.modelvertex3f = (float *)vertex3f;
8636 rsurface.modelsvector3f = NULL;
8637 rsurface.modeltvector3f = NULL;
8638 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8642 rsurface.modelvertex3f = (float *)vertex3f;
8643 rsurface.modelsvector3f = NULL;
8644 rsurface.modeltvector3f = NULL;
8645 rsurface.modelnormal3f = NULL;
8647 rsurface.modelvertexmesh = NULL;
8648 rsurface.modelvertexmesh_vertexbuffer = NULL;
8649 rsurface.modelvertexmesh_bufferoffset = 0;
8650 rsurface.modelvertex3f_vertexbuffer = 0;
8651 rsurface.modelvertex3f_bufferoffset = 0;
8652 rsurface.modelsvector3f_vertexbuffer = 0;
8653 rsurface.modelsvector3f_bufferoffset = 0;
8654 rsurface.modeltvector3f_vertexbuffer = 0;
8655 rsurface.modeltvector3f_bufferoffset = 0;
8656 rsurface.modelnormal3f_vertexbuffer = 0;
8657 rsurface.modelnormal3f_bufferoffset = 0;
8658 rsurface.modelgeneratedvertex = true;
8659 rsurface.modellightmapcolor4f = (float *)color4f;
8660 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8661 rsurface.modellightmapcolor4f_bufferoffset = 0;
8662 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8663 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8664 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8665 rsurface.modeltexcoordlightmap2f = NULL;
8666 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8667 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8668 rsurface.modelskeletalindex4ub = NULL;
8669 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8670 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8671 rsurface.modelskeletalweight4ub = NULL;
8672 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8673 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8674 rsurface.modelelement3i = (int *)element3i;
8675 rsurface.modelelement3i_indexbuffer = NULL;
8676 rsurface.modelelement3i_bufferoffset = 0;
8677 rsurface.modelelement3s = (unsigned short *)element3s;
8678 rsurface.modelelement3s_indexbuffer = NULL;
8679 rsurface.modelelement3s_bufferoffset = 0;
8680 rsurface.modellightmapoffsets = NULL;
8681 rsurface.modelsurfaces = NULL;
8682 rsurface.batchgeneratedvertex = false;
8683 rsurface.batchfirstvertex = 0;
8684 rsurface.batchnumvertices = 0;
8685 rsurface.batchfirsttriangle = 0;
8686 rsurface.batchnumtriangles = 0;
8687 rsurface.batchvertex3f = NULL;
8688 rsurface.batchvertex3f_vertexbuffer = NULL;
8689 rsurface.batchvertex3f_bufferoffset = 0;
8690 rsurface.batchsvector3f = NULL;
8691 rsurface.batchsvector3f_vertexbuffer = NULL;
8692 rsurface.batchsvector3f_bufferoffset = 0;
8693 rsurface.batchtvector3f = NULL;
8694 rsurface.batchtvector3f_vertexbuffer = NULL;
8695 rsurface.batchtvector3f_bufferoffset = 0;
8696 rsurface.batchnormal3f = NULL;
8697 rsurface.batchnormal3f_vertexbuffer = NULL;
8698 rsurface.batchnormal3f_bufferoffset = 0;
8699 rsurface.batchlightmapcolor4f = NULL;
8700 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8701 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8702 rsurface.batchtexcoordtexture2f = NULL;
8703 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8704 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8705 rsurface.batchtexcoordlightmap2f = NULL;
8706 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8707 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8708 rsurface.batchskeletalindex4ub = NULL;
8709 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8710 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8711 rsurface.batchskeletalweight4ub = NULL;
8712 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8713 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8714 rsurface.batchvertexmesh = NULL;
8715 rsurface.batchvertexmesh_vertexbuffer = NULL;
8716 rsurface.batchvertexmesh_bufferoffset = 0;
8717 rsurface.batchelement3i = NULL;
8718 rsurface.batchelement3i_indexbuffer = NULL;
8719 rsurface.batchelement3i_bufferoffset = 0;
8720 rsurface.batchelement3s = NULL;
8721 rsurface.batchelement3s_indexbuffer = NULL;
8722 rsurface.batchelement3s_bufferoffset = 0;
8723 rsurface.passcolor4f = NULL;
8724 rsurface.passcolor4f_vertexbuffer = NULL;
8725 rsurface.passcolor4f_bufferoffset = 0;
8726 rsurface.forcecurrenttextureupdate = true;
8728 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8730 if ((wantnormals || wanttangents) && !normal3f)
8732 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8733 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8735 if (wanttangents && !svector3f)
8737 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8738 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8739 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8744 float RSurf_FogPoint(const float *v)
8746 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8747 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8748 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8749 float FogHeightFade = r_refdef.fogheightfade;
8751 unsigned int fogmasktableindex;
8752 if (r_refdef.fogplaneviewabove)
8753 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8755 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8756 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8757 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8760 float RSurf_FogVertex(const float *v)
8762 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8763 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8764 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8765 float FogHeightFade = rsurface.fogheightfade;
8767 unsigned int fogmasktableindex;
8768 if (r_refdef.fogplaneviewabove)
8769 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8771 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8772 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8773 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8776 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8779 for (i = 0;i < numelements;i++)
8780 outelement3i[i] = inelement3i[i] + adjust;
8783 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8784 extern cvar_t gl_vbo;
8785 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8793 int surfacefirsttriangle;
8794 int surfacenumtriangles;
8795 int surfacefirstvertex;
8796 int surfaceendvertex;
8797 int surfacenumvertices;
8798 int batchnumsurfaces = texturenumsurfaces;
8799 int batchnumvertices;
8800 int batchnumtriangles;
8804 qboolean dynamicvertex;
8807 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8810 q3shaderinfo_deform_t *deform;
8811 const msurface_t *surface, *firstsurface;
8812 r_vertexmesh_t *vertexmesh;
8813 if (!texturenumsurfaces)
8815 // find vertex range of this surface batch
8817 firstsurface = texturesurfacelist[0];
8818 firsttriangle = firstsurface->num_firsttriangle;
8819 batchnumvertices = 0;
8820 batchnumtriangles = 0;
8821 firstvertex = endvertex = firstsurface->num_firstvertex;
8822 for (i = 0;i < texturenumsurfaces;i++)
8824 surface = texturesurfacelist[i];
8825 if (surface != firstsurface + i)
8827 surfacefirstvertex = surface->num_firstvertex;
8828 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8829 surfacenumvertices = surface->num_vertices;
8830 surfacenumtriangles = surface->num_triangles;
8831 if (firstvertex > surfacefirstvertex)
8832 firstvertex = surfacefirstvertex;
8833 if (endvertex < surfaceendvertex)
8834 endvertex = surfaceendvertex;
8835 batchnumvertices += surfacenumvertices;
8836 batchnumtriangles += surfacenumtriangles;
8839 r_refdef.stats[r_stat_batch_batches]++;
8841 r_refdef.stats[r_stat_batch_withgaps]++;
8842 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8843 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8844 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8846 // we now know the vertex range used, and if there are any gaps in it
8847 rsurface.batchfirstvertex = firstvertex;
8848 rsurface.batchnumvertices = endvertex - firstvertex;
8849 rsurface.batchfirsttriangle = firsttriangle;
8850 rsurface.batchnumtriangles = batchnumtriangles;
8852 // this variable holds flags for which properties have been updated that
8853 // may require regenerating vertexmesh array...
8856 // check if any dynamic vertex processing must occur
8857 dynamicvertex = false;
8859 // a cvar to force the dynamic vertex path to be taken, for debugging
8860 if (r_batch_debugdynamicvertexpath.integer)
8864 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8865 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8866 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8867 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8869 dynamicvertex = true;
8872 // if there is a chance of animated vertex colors, it's a dynamic batch
8873 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8877 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8878 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8879 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8880 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8882 dynamicvertex = true;
8883 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8886 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8888 switch (deform->deform)
8891 case Q3DEFORM_PROJECTIONSHADOW:
8892 case Q3DEFORM_TEXT0:
8893 case Q3DEFORM_TEXT1:
8894 case Q3DEFORM_TEXT2:
8895 case Q3DEFORM_TEXT3:
8896 case Q3DEFORM_TEXT4:
8897 case Q3DEFORM_TEXT5:
8898 case Q3DEFORM_TEXT6:
8899 case Q3DEFORM_TEXT7:
8902 case Q3DEFORM_AUTOSPRITE:
8905 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8906 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8907 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8908 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8910 dynamicvertex = true;
8911 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8912 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8914 case Q3DEFORM_AUTOSPRITE2:
8917 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8918 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8919 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8920 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8922 dynamicvertex = true;
8923 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8924 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8926 case Q3DEFORM_NORMAL:
8929 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8930 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8931 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8932 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8934 dynamicvertex = true;
8935 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8936 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8939 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8940 break; // if wavefunc is a nop, ignore this transform
8943 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8944 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8945 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8946 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8948 dynamicvertex = true;
8949 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8950 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8952 case Q3DEFORM_BULGE:
8955 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8956 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8957 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8958 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8960 dynamicvertex = true;
8961 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8962 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8965 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8966 break; // if wavefunc is a nop, ignore this transform
8969 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8970 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8971 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8972 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8974 dynamicvertex = true;
8975 batchneed |= BATCHNEED_ARRAY_VERTEX;
8976 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8980 if (rsurface.texture->materialshaderpass)
8982 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
8985 case Q3TCGEN_TEXTURE:
8987 case Q3TCGEN_LIGHTMAP:
8990 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8991 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8992 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8993 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8995 dynamicvertex = true;
8996 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8997 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8999 case Q3TCGEN_VECTOR:
9002 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9003 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9004 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9005 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9007 dynamicvertex = true;
9008 batchneed |= BATCHNEED_ARRAY_VERTEX;
9009 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9011 case Q3TCGEN_ENVIRONMENT:
9014 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9015 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9016 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9017 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9019 dynamicvertex = true;
9020 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9021 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9024 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9028 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9029 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9030 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9031 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9033 dynamicvertex = true;
9034 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9035 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9039 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9043 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9044 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9045 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9046 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9048 dynamicvertex = true;
9049 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9052 // when the model data has no vertex buffer (dynamic mesh), we need to
9054 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9055 batchneed |= BATCHNEED_NOGAPS;
9057 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9058 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9059 // we ensure this by treating the vertex batch as dynamic...
9060 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9064 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9065 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9066 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9067 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9069 dynamicvertex = true;
9074 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9075 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9076 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9077 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9078 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9079 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9080 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9081 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9084 // if needsupdate, we have to do a dynamic vertex batch for sure
9085 if (needsupdate & batchneed)
9089 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9090 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9091 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9092 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9094 dynamicvertex = true;
9097 // see if we need to build vertexmesh from arrays
9098 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9102 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9103 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9104 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9105 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9107 dynamicvertex = true;
9110 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9111 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9112 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9114 rsurface.batchvertex3f = rsurface.modelvertex3f;
9115 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9116 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9117 rsurface.batchsvector3f = rsurface.modelsvector3f;
9118 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9119 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9120 rsurface.batchtvector3f = rsurface.modeltvector3f;
9121 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9122 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9123 rsurface.batchnormal3f = rsurface.modelnormal3f;
9124 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9125 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9126 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9127 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9128 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9129 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9130 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9131 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9132 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9133 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9134 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9135 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9136 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9137 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9138 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9139 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9140 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9141 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9142 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9143 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9144 rsurface.batchelement3i = rsurface.modelelement3i;
9145 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9146 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9147 rsurface.batchelement3s = rsurface.modelelement3s;
9148 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9149 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9150 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9151 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9152 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9153 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9154 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9156 // if any dynamic vertex processing has to occur in software, we copy the
9157 // entire surface list together before processing to rebase the vertices
9158 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9160 // if any gaps exist and we do not have a static vertex buffer, we have to
9161 // copy the surface list together to avoid wasting upload bandwidth on the
9162 // vertices in the gaps.
9164 // if gaps exist and we have a static vertex buffer, we can choose whether
9165 // to combine the index buffer ranges into one dynamic index buffer or
9166 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9168 // in many cases the batch is reduced to one draw call.
9170 rsurface.batchmultidraw = false;
9171 rsurface.batchmultidrawnumsurfaces = 0;
9172 rsurface.batchmultidrawsurfacelist = NULL;
9176 // static vertex data, just set pointers...
9177 rsurface.batchgeneratedvertex = false;
9178 // if there are gaps, we want to build a combined index buffer,
9179 // otherwise use the original static buffer with an appropriate offset
9182 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9183 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9184 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9185 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9186 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9188 rsurface.batchmultidraw = true;
9189 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9190 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9193 // build a new triangle elements array for this batch
9194 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9195 rsurface.batchfirsttriangle = 0;
9197 for (i = 0;i < texturenumsurfaces;i++)
9199 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9200 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9201 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9202 numtriangles += surfacenumtriangles;
9204 rsurface.batchelement3i_indexbuffer = NULL;
9205 rsurface.batchelement3i_bufferoffset = 0;
9206 rsurface.batchelement3s = NULL;
9207 rsurface.batchelement3s_indexbuffer = NULL;
9208 rsurface.batchelement3s_bufferoffset = 0;
9209 if (endvertex <= 65536)
9211 // make a 16bit (unsigned short) index array if possible
9212 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9213 for (i = 0;i < numtriangles*3;i++)
9214 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9216 // upload buffer data for the copytriangles batch
9217 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9219 if (rsurface.batchelement3s)
9220 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9221 else if (rsurface.batchelement3i)
9222 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9227 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9228 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9229 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9230 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9235 // something needs software processing, do it for real...
9236 // we only directly handle separate array data in this case and then
9237 // generate interleaved data if needed...
9238 rsurface.batchgeneratedvertex = true;
9239 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9240 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9241 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9242 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9244 // now copy the vertex data into a combined array and make an index array
9245 // (this is what Quake3 does all the time)
9246 // we also apply any skeletal animation here that would have been done in
9247 // the vertex shader, because most of the dynamic vertex animation cases
9248 // need actual vertex positions and normals
9249 //if (dynamicvertex)
9251 rsurface.batchvertexmesh = NULL;
9252 rsurface.batchvertexmesh_vertexbuffer = NULL;
9253 rsurface.batchvertexmesh_bufferoffset = 0;
9254 rsurface.batchvertex3f = NULL;
9255 rsurface.batchvertex3f_vertexbuffer = NULL;
9256 rsurface.batchvertex3f_bufferoffset = 0;
9257 rsurface.batchsvector3f = NULL;
9258 rsurface.batchsvector3f_vertexbuffer = NULL;
9259 rsurface.batchsvector3f_bufferoffset = 0;
9260 rsurface.batchtvector3f = NULL;
9261 rsurface.batchtvector3f_vertexbuffer = NULL;
9262 rsurface.batchtvector3f_bufferoffset = 0;
9263 rsurface.batchnormal3f = NULL;
9264 rsurface.batchnormal3f_vertexbuffer = NULL;
9265 rsurface.batchnormal3f_bufferoffset = 0;
9266 rsurface.batchlightmapcolor4f = NULL;
9267 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9268 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9269 rsurface.batchtexcoordtexture2f = NULL;
9270 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9271 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9272 rsurface.batchtexcoordlightmap2f = NULL;
9273 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9274 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9275 rsurface.batchskeletalindex4ub = NULL;
9276 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9277 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9278 rsurface.batchskeletalweight4ub = NULL;
9279 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9280 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9281 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9282 rsurface.batchelement3i_indexbuffer = NULL;
9283 rsurface.batchelement3i_bufferoffset = 0;
9284 rsurface.batchelement3s = NULL;
9285 rsurface.batchelement3s_indexbuffer = NULL;
9286 rsurface.batchelement3s_bufferoffset = 0;
9287 rsurface.batchskeletaltransform3x4buffer = NULL;
9288 rsurface.batchskeletaltransform3x4offset = 0;
9289 rsurface.batchskeletaltransform3x4size = 0;
9290 // we'll only be setting up certain arrays as needed
9291 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9292 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9293 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9294 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9295 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9296 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9297 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9299 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9300 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9302 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9303 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9304 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9305 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9306 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9307 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9308 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9310 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9311 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9315 for (i = 0;i < texturenumsurfaces;i++)
9317 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9318 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9319 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9320 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9321 // copy only the data requested
9322 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9323 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9324 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9326 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9328 if (rsurface.batchvertex3f)
9329 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9331 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9333 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9335 if (rsurface.modelnormal3f)
9336 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9338 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9340 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9342 if (rsurface.modelsvector3f)
9344 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9345 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9349 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9350 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9353 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9355 if (rsurface.modellightmapcolor4f)
9356 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9358 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9360 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9362 if (rsurface.modeltexcoordtexture2f)
9363 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9365 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9367 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9369 if (rsurface.modeltexcoordlightmap2f)
9370 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9372 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9374 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9376 if (rsurface.modelskeletalindex4ub)
9378 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9379 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9383 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9384 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9385 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9386 for (j = 0;j < surfacenumvertices;j++)
9391 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9392 numvertices += surfacenumvertices;
9393 numtriangles += surfacenumtriangles;
9396 // generate a 16bit index array as well if possible
9397 // (in general, dynamic batches fit)
9398 if (numvertices <= 65536)
9400 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9401 for (i = 0;i < numtriangles*3;i++)
9402 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9405 // since we've copied everything, the batch now starts at 0
9406 rsurface.batchfirstvertex = 0;
9407 rsurface.batchnumvertices = batchnumvertices;
9408 rsurface.batchfirsttriangle = 0;
9409 rsurface.batchnumtriangles = batchnumtriangles;
9412 // apply skeletal animation that would have been done in the vertex shader
9413 if (rsurface.batchskeletaltransform3x4)
9415 const unsigned char *si;
9416 const unsigned char *sw;
9418 const float *b = rsurface.batchskeletaltransform3x4;
9419 float *vp, *vs, *vt, *vn;
9421 float m[3][4], n[3][4];
9422 float tp[3], ts[3], tt[3], tn[3];
9423 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9424 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9425 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9426 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9427 si = rsurface.batchskeletalindex4ub;
9428 sw = rsurface.batchskeletalweight4ub;
9429 vp = rsurface.batchvertex3f;
9430 vs = rsurface.batchsvector3f;
9431 vt = rsurface.batchtvector3f;
9432 vn = rsurface.batchnormal3f;
9433 memset(m[0], 0, sizeof(m));
9434 memset(n[0], 0, sizeof(n));
9435 for (i = 0;i < batchnumvertices;i++)
9437 t[0] = b + si[0]*12;
9440 // common case - only one matrix
9454 else if (sw[2] + sw[3])
9457 t[1] = b + si[1]*12;
9458 t[2] = b + si[2]*12;
9459 t[3] = b + si[3]*12;
9460 w[0] = sw[0] * (1.0f / 255.0f);
9461 w[1] = sw[1] * (1.0f / 255.0f);
9462 w[2] = sw[2] * (1.0f / 255.0f);
9463 w[3] = sw[3] * (1.0f / 255.0f);
9464 // blend the matrices
9465 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9466 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9467 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9468 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9469 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9470 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9471 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9472 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9473 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9474 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9475 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9476 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9481 t[1] = b + si[1]*12;
9482 w[0] = sw[0] * (1.0f / 255.0f);
9483 w[1] = sw[1] * (1.0f / 255.0f);
9484 // blend the matrices
9485 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9486 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9487 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9488 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9489 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9490 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9491 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9492 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9493 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9494 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9495 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9496 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9500 // modify the vertex
9502 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9503 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9504 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9508 // the normal transformation matrix is a set of cross products...
9509 CrossProduct(m[1], m[2], n[0]);
9510 CrossProduct(m[2], m[0], n[1]);
9511 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9513 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9514 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9515 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9516 VectorNormalize(vn);
9521 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9522 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9523 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9524 VectorNormalize(vs);
9527 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9528 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9529 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9530 VectorNormalize(vt);
9535 rsurface.batchskeletaltransform3x4 = NULL;
9536 rsurface.batchskeletalnumtransforms = 0;
9539 // q1bsp surfaces rendered in vertex color mode have to have colors
9540 // calculated based on lightstyles
9541 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9543 // generate color arrays for the surfaces in this list
9548 const unsigned char *lm;
9549 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9550 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9551 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9553 for (i = 0;i < texturenumsurfaces;i++)
9555 surface = texturesurfacelist[i];
9556 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9557 surfacenumvertices = surface->num_vertices;
9558 if (surface->lightmapinfo->samples)
9560 for (j = 0;j < surfacenumvertices;j++)
9562 lm = surface->lightmapinfo->samples + offsets[j];
9563 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9564 VectorScale(lm, scale, c);
9565 if (surface->lightmapinfo->styles[1] != 255)
9567 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9569 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9570 VectorMA(c, scale, lm, c);
9571 if (surface->lightmapinfo->styles[2] != 255)
9574 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9575 VectorMA(c, scale, lm, c);
9576 if (surface->lightmapinfo->styles[3] != 255)
9579 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9580 VectorMA(c, scale, lm, c);
9587 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);
9593 for (j = 0;j < surfacenumvertices;j++)
9595 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9602 // if vertices are deformed (sprite flares and things in maps, possibly
9603 // water waves, bulges and other deformations), modify the copied vertices
9605 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9608 switch (deform->deform)
9611 case Q3DEFORM_PROJECTIONSHADOW:
9612 case Q3DEFORM_TEXT0:
9613 case Q3DEFORM_TEXT1:
9614 case Q3DEFORM_TEXT2:
9615 case Q3DEFORM_TEXT3:
9616 case Q3DEFORM_TEXT4:
9617 case Q3DEFORM_TEXT5:
9618 case Q3DEFORM_TEXT6:
9619 case Q3DEFORM_TEXT7:
9622 case Q3DEFORM_AUTOSPRITE:
9623 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9624 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9625 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9626 VectorNormalize(newforward);
9627 VectorNormalize(newright);
9628 VectorNormalize(newup);
9629 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9630 // rsurface.batchvertex3f_vertexbuffer = NULL;
9631 // rsurface.batchvertex3f_bufferoffset = 0;
9632 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9633 // rsurface.batchsvector3f_vertexbuffer = NULL;
9634 // rsurface.batchsvector3f_bufferoffset = 0;
9635 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9636 // rsurface.batchtvector3f_vertexbuffer = NULL;
9637 // rsurface.batchtvector3f_bufferoffset = 0;
9638 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9639 // rsurface.batchnormal3f_vertexbuffer = NULL;
9640 // rsurface.batchnormal3f_bufferoffset = 0;
9641 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9642 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9643 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9644 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9645 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);
9646 // a single autosprite surface can contain multiple sprites...
9647 for (j = 0;j < batchnumvertices - 3;j += 4)
9649 VectorClear(center);
9650 for (i = 0;i < 4;i++)
9651 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9652 VectorScale(center, 0.25f, center);
9653 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9654 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9655 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9656 for (i = 0;i < 4;i++)
9658 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9659 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9662 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9663 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9664 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);
9666 case Q3DEFORM_AUTOSPRITE2:
9667 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9668 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9669 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9670 VectorNormalize(newforward);
9671 VectorNormalize(newright);
9672 VectorNormalize(newup);
9673 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9674 // rsurface.batchvertex3f_vertexbuffer = NULL;
9675 // rsurface.batchvertex3f_bufferoffset = 0;
9677 const float *v1, *v2;
9687 memset(shortest, 0, sizeof(shortest));
9688 // a single autosprite surface can contain multiple sprites...
9689 for (j = 0;j < batchnumvertices - 3;j += 4)
9691 VectorClear(center);
9692 for (i = 0;i < 4;i++)
9693 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9694 VectorScale(center, 0.25f, center);
9695 // find the two shortest edges, then use them to define the
9696 // axis vectors for rotating around the central axis
9697 for (i = 0;i < 6;i++)
9699 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9700 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9701 l = VectorDistance2(v1, v2);
9702 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9704 l += (1.0f / 1024.0f);
9705 if (shortest[0].length2 > l || i == 0)
9707 shortest[1] = shortest[0];
9708 shortest[0].length2 = l;
9709 shortest[0].v1 = v1;
9710 shortest[0].v2 = v2;
9712 else if (shortest[1].length2 > l || i == 1)
9714 shortest[1].length2 = l;
9715 shortest[1].v1 = v1;
9716 shortest[1].v2 = v2;
9719 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9720 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9721 // this calculates the right vector from the shortest edge
9722 // and the up vector from the edge midpoints
9723 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9724 VectorNormalize(right);
9725 VectorSubtract(end, start, up);
9726 VectorNormalize(up);
9727 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9728 VectorSubtract(rsurface.localvieworigin, center, forward);
9729 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9730 VectorNegate(forward, forward);
9731 VectorReflect(forward, 0, up, forward);
9732 VectorNormalize(forward);
9733 CrossProduct(up, forward, newright);
9734 VectorNormalize(newright);
9735 // rotate the quad around the up axis vector, this is made
9736 // especially easy by the fact we know the quad is flat,
9737 // so we only have to subtract the center position and
9738 // measure distance along the right vector, and then
9739 // multiply that by the newright vector and add back the
9741 // we also need to subtract the old position to undo the
9742 // displacement from the center, which we do with a
9743 // DotProduct, the subtraction/addition of center is also
9744 // optimized into DotProducts here
9745 l = DotProduct(right, center);
9746 for (i = 0;i < 4;i++)
9748 v1 = rsurface.batchvertex3f + 3*(j+i);
9749 f = DotProduct(right, v1) - l;
9750 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9754 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9756 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9757 // rsurface.batchnormal3f_vertexbuffer = NULL;
9758 // rsurface.batchnormal3f_bufferoffset = 0;
9759 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9761 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9763 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9764 // rsurface.batchsvector3f_vertexbuffer = NULL;
9765 // rsurface.batchsvector3f_bufferoffset = 0;
9766 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9767 // rsurface.batchtvector3f_vertexbuffer = NULL;
9768 // rsurface.batchtvector3f_bufferoffset = 0;
9769 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);
9772 case Q3DEFORM_NORMAL:
9773 // deform the normals to make reflections wavey
9774 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9775 rsurface.batchnormal3f_vertexbuffer = NULL;
9776 rsurface.batchnormal3f_bufferoffset = 0;
9777 for (j = 0;j < batchnumvertices;j++)
9780 float *normal = rsurface.batchnormal3f + 3*j;
9781 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9782 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9783 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9784 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9785 VectorNormalize(normal);
9787 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9789 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9790 // rsurface.batchsvector3f_vertexbuffer = NULL;
9791 // rsurface.batchsvector3f_bufferoffset = 0;
9792 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9793 // rsurface.batchtvector3f_vertexbuffer = NULL;
9794 // rsurface.batchtvector3f_bufferoffset = 0;
9795 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);
9799 // deform vertex array to make wavey water and flags and such
9800 waveparms[0] = deform->waveparms[0];
9801 waveparms[1] = deform->waveparms[1];
9802 waveparms[2] = deform->waveparms[2];
9803 waveparms[3] = deform->waveparms[3];
9804 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9805 break; // if wavefunc is a nop, don't make a dynamic vertex array
9806 // this is how a divisor of vertex influence on deformation
9807 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9808 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9809 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9810 // rsurface.batchvertex3f_vertexbuffer = NULL;
9811 // rsurface.batchvertex3f_bufferoffset = 0;
9812 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9813 // rsurface.batchnormal3f_vertexbuffer = NULL;
9814 // rsurface.batchnormal3f_bufferoffset = 0;
9815 for (j = 0;j < batchnumvertices;j++)
9817 // if the wavefunc depends on time, evaluate it per-vertex
9820 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9821 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9823 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9825 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9826 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9827 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9829 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9830 // rsurface.batchsvector3f_vertexbuffer = NULL;
9831 // rsurface.batchsvector3f_bufferoffset = 0;
9832 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9833 // rsurface.batchtvector3f_vertexbuffer = NULL;
9834 // rsurface.batchtvector3f_bufferoffset = 0;
9835 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);
9838 case Q3DEFORM_BULGE:
9839 // deform vertex array to make the surface have moving bulges
9840 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9841 // rsurface.batchvertex3f_vertexbuffer = NULL;
9842 // rsurface.batchvertex3f_bufferoffset = 0;
9843 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9844 // rsurface.batchnormal3f_vertexbuffer = NULL;
9845 // rsurface.batchnormal3f_bufferoffset = 0;
9846 for (j = 0;j < batchnumvertices;j++)
9848 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9849 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9851 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9852 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9853 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9855 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9856 // rsurface.batchsvector3f_vertexbuffer = NULL;
9857 // rsurface.batchsvector3f_bufferoffset = 0;
9858 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9859 // rsurface.batchtvector3f_vertexbuffer = NULL;
9860 // rsurface.batchtvector3f_bufferoffset = 0;
9861 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);
9865 // deform vertex array
9866 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9867 break; // if wavefunc is a nop, don't make a dynamic vertex array
9868 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9869 VectorScale(deform->parms, scale, waveparms);
9870 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9871 // rsurface.batchvertex3f_vertexbuffer = NULL;
9872 // rsurface.batchvertex3f_bufferoffset = 0;
9873 for (j = 0;j < batchnumvertices;j++)
9874 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9879 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9881 // generate texcoords based on the chosen texcoord source
9882 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9885 case Q3TCGEN_TEXTURE:
9887 case Q3TCGEN_LIGHTMAP:
9888 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9889 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9890 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9891 if (rsurface.batchtexcoordlightmap2f)
9892 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9894 case Q3TCGEN_VECTOR:
9895 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9896 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9897 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9898 for (j = 0;j < batchnumvertices;j++)
9900 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9901 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9904 case Q3TCGEN_ENVIRONMENT:
9905 // make environment reflections using a spheremap
9906 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9907 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9908 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9909 for (j = 0;j < batchnumvertices;j++)
9911 // identical to Q3A's method, but executed in worldspace so
9912 // carried models can be shiny too
9914 float viewer[3], d, reflected[3], worldreflected[3];
9916 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9917 // VectorNormalize(viewer);
9919 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9921 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9922 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9923 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9924 // note: this is proportinal to viewer, so we can normalize later
9926 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9927 VectorNormalize(worldreflected);
9929 // note: this sphere map only uses world x and z!
9930 // so positive and negative y will LOOK THE SAME.
9931 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9932 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9936 // the only tcmod that needs software vertex processing is turbulent, so
9937 // check for it here and apply the changes if needed
9938 // and we only support that as the first one
9939 // (handling a mixture of turbulent and other tcmods would be problematic
9940 // without punting it entirely to a software path)
9941 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9943 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
9944 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
9945 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9946 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9947 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9948 for (j = 0;j < batchnumvertices;j++)
9950 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);
9951 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9956 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9958 // convert the modified arrays to vertex structs
9959 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9960 // rsurface.batchvertexmesh_vertexbuffer = NULL;
9961 // rsurface.batchvertexmesh_bufferoffset = 0;
9962 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9963 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9964 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9965 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9966 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9967 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9968 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9970 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9972 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9973 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9976 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9977 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9978 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9979 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9980 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9981 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9982 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9983 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9984 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9985 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9987 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9989 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9990 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9995 // upload buffer data for the dynamic batch
9996 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9998 if (rsurface.batchvertexmesh)
9999 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10002 if (rsurface.batchvertex3f)
10003 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10004 if (rsurface.batchsvector3f)
10005 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10006 if (rsurface.batchtvector3f)
10007 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10008 if (rsurface.batchnormal3f)
10009 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10010 if (rsurface.batchlightmapcolor4f)
10011 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10012 if (rsurface.batchtexcoordtexture2f)
10013 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10014 if (rsurface.batchtexcoordlightmap2f)
10015 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10016 if (rsurface.batchskeletalindex4ub)
10017 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10018 if (rsurface.batchskeletalweight4ub)
10019 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10021 if (rsurface.batchelement3s)
10022 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10023 else if (rsurface.batchelement3i)
10024 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10028 void RSurf_DrawBatch(void)
10030 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10031 // through the pipeline, killing it earlier in the pipeline would have
10032 // per-surface overhead rather than per-batch overhead, so it's best to
10033 // reject it here, before it hits glDraw.
10034 if (rsurface.batchnumtriangles == 0)
10037 // batch debugging code
10038 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10044 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10045 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10048 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10050 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10052 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10053 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);
10060 if (rsurface.batchmultidraw)
10062 // issue multiple draws rather than copying index data
10063 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10064 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10065 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10066 for (i = 0;i < numsurfaces;)
10068 // combine consecutive surfaces as one draw
10069 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10070 if (surfacelist[j] != surfacelist[k] + 1)
10072 firstvertex = surfacelist[i]->num_firstvertex;
10073 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10074 firsttriangle = surfacelist[i]->num_firsttriangle;
10075 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10076 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);
10082 // there is only one consecutive run of index data (may have been combined)
10083 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);
10087 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10089 // pick the closest matching water plane
10090 int planeindex, vertexindex, bestplaneindex = -1;
10094 r_waterstate_waterplane_t *p;
10095 qboolean prepared = false;
10097 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10099 if(p->camera_entity != rsurface.texture->camera_entity)
10104 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10106 if(rsurface.batchnumvertices == 0)
10109 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10111 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10112 d += fabs(PlaneDiff(vert, &p->plane));
10114 if (bestd > d || bestplaneindex < 0)
10117 bestplaneindex = planeindex;
10120 return bestplaneindex;
10121 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10122 // this situation though, as it might be better to render single larger
10123 // batches with useless stuff (backface culled for example) than to
10124 // render multiple smaller batches
10127 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10130 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10131 rsurface.passcolor4f_vertexbuffer = 0;
10132 rsurface.passcolor4f_bufferoffset = 0;
10133 for (i = 0;i < rsurface.batchnumvertices;i++)
10134 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10137 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10144 if (rsurface.passcolor4f)
10146 // generate color arrays
10147 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10148 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10149 rsurface.passcolor4f_vertexbuffer = 0;
10150 rsurface.passcolor4f_bufferoffset = 0;
10151 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)
10153 f = RSurf_FogVertex(v);
10162 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10163 rsurface.passcolor4f_vertexbuffer = 0;
10164 rsurface.passcolor4f_bufferoffset = 0;
10165 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10167 f = RSurf_FogVertex(v);
10176 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10183 if (!rsurface.passcolor4f)
10185 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10186 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10187 rsurface.passcolor4f_vertexbuffer = 0;
10188 rsurface.passcolor4f_bufferoffset = 0;
10189 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)
10191 f = RSurf_FogVertex(v);
10192 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10193 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10194 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10199 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10204 if (!rsurface.passcolor4f)
10206 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10207 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10208 rsurface.passcolor4f_vertexbuffer = 0;
10209 rsurface.passcolor4f_bufferoffset = 0;
10210 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10219 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10224 if (!rsurface.passcolor4f)
10226 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10227 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10228 rsurface.passcolor4f_vertexbuffer = 0;
10229 rsurface.passcolor4f_bufferoffset = 0;
10230 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10232 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10233 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10234 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10239 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10242 rsurface.passcolor4f = NULL;
10243 rsurface.passcolor4f_vertexbuffer = 0;
10244 rsurface.passcolor4f_bufferoffset = 0;
10245 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10246 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10247 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10248 GL_Color(r, g, b, a);
10249 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10250 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10251 R_Mesh_TexMatrix(0, NULL);
10255 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10257 // TODO: optimize applyfog && applycolor case
10258 // just apply fog if necessary, and tint the fog color array if necessary
10259 rsurface.passcolor4f = NULL;
10260 rsurface.passcolor4f_vertexbuffer = 0;
10261 rsurface.passcolor4f_bufferoffset = 0;
10262 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10263 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10264 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10265 GL_Color(r, g, b, a);
10269 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10272 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10273 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10274 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10275 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10276 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10277 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10278 GL_Color(r, g, b, a);
10282 static void RSurf_DrawBatch_GL11_ClampColor(void)
10287 if (!rsurface.passcolor4f)
10289 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10291 c2[0] = bound(0.0f, c1[0], 1.0f);
10292 c2[1] = bound(0.0f, c1[1], 1.0f);
10293 c2[2] = bound(0.0f, c1[2], 1.0f);
10294 c2[3] = bound(0.0f, c1[3], 1.0f);
10298 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10308 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10309 rsurface.passcolor4f_vertexbuffer = 0;
10310 rsurface.passcolor4f_bufferoffset = 0;
10311 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)
10313 f = -DotProduct(r_refdef.view.forward, n);
10315 f = f * 0.85 + 0.15; // work around so stuff won't get black
10316 f *= fakelightintensity;
10317 Vector4Set(c, f, f, f, 1);
10321 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10323 RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10324 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10325 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10326 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10327 GL_Color(r, g, b, a);
10331 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10339 vec3_t ambientcolor;
10340 vec3_t diffusecolor;
10344 VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10345 f = 0.5f * lightmapintensity;
10346 ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10347 ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10348 ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10349 diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10350 diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10351 diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10353 if (VectorLength2(diffusecolor) > 0)
10355 // q3-style directional shading
10356 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10357 rsurface.passcolor4f_vertexbuffer = 0;
10358 rsurface.passcolor4f_bufferoffset = 0;
10359 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)
10361 if ((f = DotProduct(n, lightdir)) > 0)
10362 VectorMA(ambientcolor, f, diffusecolor, c);
10364 VectorCopy(ambientcolor, c);
10371 *applycolor = false;
10375 *r = ambientcolor[0];
10376 *g = ambientcolor[1];
10377 *b = ambientcolor[2];
10378 rsurface.passcolor4f = NULL;
10379 rsurface.passcolor4f_vertexbuffer = 0;
10380 rsurface.passcolor4f_bufferoffset = 0;
10384 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10386 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10387 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10388 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10389 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10390 GL_Color(r, g, b, a);
10394 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10402 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10403 rsurface.passcolor4f_vertexbuffer = 0;
10404 rsurface.passcolor4f_bufferoffset = 0;
10406 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10408 f = 1 - RSurf_FogVertex(v);
10416 void RSurf_SetupDepthAndCulling(void)
10418 // submodels are biased to avoid z-fighting with world surfaces that they
10419 // may be exactly overlapping (avoids z-fighting artifacts on certain
10420 // doors and things in Quake maps)
10421 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10422 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10423 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10424 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10427 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10430 // transparent sky would be ridiculous
10431 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10433 R_SetupShader_Generic_NoTexture(false, false);
10434 skyrenderlater = true;
10435 RSurf_SetupDepthAndCulling();
10436 GL_DepthMask(true);
10438 // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10439 if (r_sky_scissor.integer)
10441 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10442 for (i = 0; i < texturenumsurfaces; i++)
10444 const msurface_t *surf = texturesurfacelist[i];
10447 float mins[3], maxs[3];
10449 for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10451 Matrix4x4_Transform(&rsurface.matrix, v, p);
10454 if (mins[0] > p[0]) mins[0] = p[0];
10455 if (mins[1] > p[1]) mins[1] = p[1];
10456 if (mins[2] > p[2]) mins[2] = p[2];
10457 if (maxs[0] < p[0]) maxs[0] = p[0];
10458 if (maxs[1] < p[1]) maxs[1] = p[1];
10459 if (maxs[2] < p[2]) maxs[2] = p[2];
10463 VectorCopy(p, mins);
10464 VectorCopy(p, maxs);
10467 if (!R_ScissorForBBox(mins, maxs, scissor))
10471 if (skyscissor[0] > scissor[0])
10473 skyscissor[2] += skyscissor[0] - scissor[0];
10474 skyscissor[0] = scissor[0];
10476 if (skyscissor[1] > scissor[1])
10478 skyscissor[3] += skyscissor[1] - scissor[1];
10479 skyscissor[1] = scissor[1];
10481 if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10482 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10483 if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10484 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10487 Vector4Copy(scissor, skyscissor);
10492 // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10493 // skymasking on them, and Quake3 never did sky masking (unlike
10494 // software Quake and software Quake2), so disable the sky masking
10495 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10496 // and skymasking also looks very bad when noclipping outside the
10497 // level, so don't use it then either.
10498 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10500 R_Mesh_ResetTextureState();
10501 if (skyrendermasked)
10503 R_SetupShader_DepthOrShadow(false, false, false);
10504 // depth-only (masking)
10505 GL_ColorMask(0, 0, 0, 0);
10506 // just to make sure that braindead drivers don't draw
10507 // anything despite that colormask...
10508 GL_BlendFunc(GL_ZERO, GL_ONE);
10509 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10510 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10514 R_SetupShader_Generic_NoTexture(false, false);
10516 GL_BlendFunc(GL_ONE, GL_ZERO);
10517 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10518 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10519 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10522 if (skyrendermasked)
10523 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10525 R_Mesh_ResetTextureState();
10526 GL_Color(1, 1, 1, 1);
10529 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10530 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10531 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10533 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10537 // render screenspace normalmap to texture
10538 GL_DepthMask(true);
10539 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10544 // bind lightmap texture
10546 // water/refraction/reflection/camera surfaces have to be handled specially
10547 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10549 int start, end, startplaneindex;
10550 for (start = 0;start < texturenumsurfaces;start = end)
10552 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10553 if(startplaneindex < 0)
10555 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10556 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10560 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10562 // now that we have a batch using the same planeindex, render it
10563 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10565 // render water or distortion background
10566 GL_DepthMask(true);
10567 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10569 // blend surface on top
10570 GL_DepthMask(false);
10571 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10574 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10576 // render surface with reflection texture as input
10577 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10578 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10585 // render surface batch normally
10586 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10587 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10591 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10593 // OpenGL 1.3 path - anything not completely ancient
10594 qboolean applycolor;
10597 const texturelayer_t *layer;
10598 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10599 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10601 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10604 int layertexrgbscale;
10605 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10607 if (layerindex == 0)
10608 GL_AlphaTest(true);
10611 GL_AlphaTest(false);
10612 GL_DepthFunc(GL_EQUAL);
10615 GL_DepthMask(layer->depthmask && writedepth);
10616 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10617 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10619 layertexrgbscale = 4;
10620 VectorScale(layer->color, 0.25f, layercolor);
10622 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10624 layertexrgbscale = 2;
10625 VectorScale(layer->color, 0.5f, layercolor);
10629 layertexrgbscale = 1;
10630 VectorScale(layer->color, 1.0f, layercolor);
10632 layercolor[3] = layer->color[3];
10633 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10634 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10635 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10636 switch (layer->type)
10638 case TEXTURELAYERTYPE_LITTEXTURE:
10639 // single-pass lightmapped texture with 2x rgbscale
10640 R_Mesh_TexBind(0, r_texture_white);
10641 R_Mesh_TexMatrix(0, NULL);
10642 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10643 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10644 R_Mesh_TexBind(1, layer->texture);
10645 R_Mesh_TexMatrix(1, &layer->texmatrix);
10646 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10647 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10648 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10649 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10650 else if (FAKELIGHT_ENABLED)
10651 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10652 else if (rsurface.uselightmaptexture)
10653 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10655 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10657 case TEXTURELAYERTYPE_TEXTURE:
10658 // singletexture unlit texture with transparency support
10659 R_Mesh_TexBind(0, layer->texture);
10660 R_Mesh_TexMatrix(0, &layer->texmatrix);
10661 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10662 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10663 R_Mesh_TexBind(1, 0);
10664 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10665 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10667 case TEXTURELAYERTYPE_FOG:
10668 // singletexture fogging
10669 if (layer->texture)
10671 R_Mesh_TexBind(0, layer->texture);
10672 R_Mesh_TexMatrix(0, &layer->texmatrix);
10673 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10674 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10678 R_Mesh_TexBind(0, 0);
10679 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10681 R_Mesh_TexBind(1, 0);
10682 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10683 // generate a color array for the fog pass
10684 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10685 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10689 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10692 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10694 GL_DepthFunc(GL_LEQUAL);
10695 GL_AlphaTest(false);
10699 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10701 // OpenGL 1.1 - crusty old voodoo path
10704 const texturelayer_t *layer;
10705 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10706 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10708 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10710 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10712 if (layerindex == 0)
10713 GL_AlphaTest(true);
10716 GL_AlphaTest(false);
10717 GL_DepthFunc(GL_EQUAL);
10720 GL_DepthMask(layer->depthmask && writedepth);
10721 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10722 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10723 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10724 switch (layer->type)
10726 case TEXTURELAYERTYPE_LITTEXTURE:
10727 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10729 // two-pass lit texture with 2x rgbscale
10730 // first the lightmap pass
10731 R_Mesh_TexBind(0, r_texture_white);
10732 R_Mesh_TexMatrix(0, NULL);
10733 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10734 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10735 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10736 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10737 else if (FAKELIGHT_ENABLED)
10738 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10739 else if (rsurface.uselightmaptexture)
10740 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10742 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10743 // then apply the texture to it
10744 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10745 R_Mesh_TexBind(0, layer->texture);
10746 R_Mesh_TexMatrix(0, &layer->texmatrix);
10747 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10748 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10749 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);
10753 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10754 R_Mesh_TexBind(0, layer->texture);
10755 R_Mesh_TexMatrix(0, &layer->texmatrix);
10756 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10757 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10758 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10759 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);
10760 else if (FAKELIGHT_ENABLED)
10761 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);
10763 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);
10766 case TEXTURELAYERTYPE_TEXTURE:
10767 // singletexture unlit texture with transparency support
10768 R_Mesh_TexBind(0, layer->texture);
10769 R_Mesh_TexMatrix(0, &layer->texmatrix);
10770 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10771 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10772 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);
10774 case TEXTURELAYERTYPE_FOG:
10775 // singletexture fogging
10776 if (layer->texture)
10778 R_Mesh_TexBind(0, layer->texture);
10779 R_Mesh_TexMatrix(0, &layer->texmatrix);
10780 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10781 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10785 R_Mesh_TexBind(0, 0);
10786 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10788 // generate a color array for the fog pass
10789 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10790 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10794 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10797 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10799 GL_DepthFunc(GL_LEQUAL);
10800 GL_AlphaTest(false);
10804 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10808 r_vertexgeneric_t *batchvertex;
10810 texture_t *t = rsurface.texture;
10812 // R_Mesh_ResetTextureState();
10813 R_SetupShader_Generic_NoTexture(false, false);
10815 if(t && t->currentskinframe)
10817 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10818 c[3] *= t->currentalpha;
10828 if (t->pantstexture || t->shirttexture)
10830 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10831 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10832 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10835 // brighten it up (as texture value 127 means "unlit")
10836 c[0] *= 2 * r_refdef.view.colorscale;
10837 c[1] *= 2 * r_refdef.view.colorscale;
10838 c[2] *= 2 * r_refdef.view.colorscale;
10840 if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10841 c[3] *= r_wateralpha.value;
10843 if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10845 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10846 GL_DepthMask(false);
10848 else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10850 GL_BlendFunc(GL_ONE, GL_ONE);
10851 GL_DepthMask(false);
10853 else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10855 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10856 GL_DepthMask(false);
10858 else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10860 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10861 GL_DepthMask(false);
10865 GL_BlendFunc(GL_ONE, GL_ZERO);
10866 GL_DepthMask(writedepth);
10869 if (r_showsurfaces.integer == 3)
10871 rsurface.passcolor4f = NULL;
10873 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10875 qboolean applycolor = true;
10878 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10880 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10882 else if (FAKELIGHT_ENABLED)
10884 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10886 RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10890 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10892 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10893 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10894 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10895 RSurf_DrawBatch_GL11_ApplyAmbient();
10898 if(!rsurface.passcolor4f)
10899 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10901 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10902 if(r_refdef.fogenabled)
10903 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10904 RSurf_DrawBatch_GL11_ClampColor();
10906 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10907 R_SetupShader_Generic_NoTexture(false, false);
10910 else if (!r_refdef.view.showdebug)
10912 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10913 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10914 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10916 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10917 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10919 R_Mesh_PrepareVertices_Generic_Unlock();
10922 else if (r_showsurfaces.integer == 4)
10924 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10925 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10926 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10928 unsigned char d = (vi << 3) * (1.0f / 256.0f);
10929 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10930 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10932 R_Mesh_PrepareVertices_Generic_Unlock();
10935 else if (r_showsurfaces.integer == 2)
10938 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10939 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10940 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10942 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10943 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10944 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10945 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10946 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10947 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10948 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10950 R_Mesh_PrepareVertices_Generic_Unlock();
10951 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10955 int texturesurfaceindex;
10957 const msurface_t *surface;
10958 float surfacecolor4f[4];
10959 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10960 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10962 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10964 surface = texturesurfacelist[texturesurfaceindex];
10965 k = (int)(((size_t)surface) / sizeof(msurface_t));
10966 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10967 for (j = 0;j < surface->num_vertices;j++)
10969 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10970 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10974 R_Mesh_PrepareVertices_Generic_Unlock();
10979 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10982 RSurf_SetupDepthAndCulling();
10983 if (r_showsurfaces.integer)
10985 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10988 switch (vid.renderpath)
10990 case RENDERPATH_GL20:
10991 case RENDERPATH_D3D9:
10992 case RENDERPATH_D3D10:
10993 case RENDERPATH_D3D11:
10994 case RENDERPATH_SOFT:
10995 case RENDERPATH_GLES2:
10996 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10998 case RENDERPATH_GL13:
10999 case RENDERPATH_GLES1:
11000 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11002 case RENDERPATH_GL11:
11003 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11009 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11012 int texturenumsurfaces, endsurface;
11013 texture_t *texture;
11014 const msurface_t *surface;
11015 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11017 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11018 RSurf_ActiveModelEntity(ent, false, false, false);
11021 switch (vid.renderpath)
11023 case RENDERPATH_GL20:
11024 case RENDERPATH_D3D9:
11025 case RENDERPATH_D3D10:
11026 case RENDERPATH_D3D11:
11027 case RENDERPATH_SOFT:
11028 case RENDERPATH_GLES2:
11029 RSurf_ActiveModelEntity(ent, true, true, false);
11031 case RENDERPATH_GL11:
11032 case RENDERPATH_GL13:
11033 case RENDERPATH_GLES1:
11034 RSurf_ActiveModelEntity(ent, true, false, false);
11039 if (r_transparentdepthmasking.integer)
11041 qboolean setup = false;
11042 for (i = 0;i < numsurfaces;i = j)
11045 surface = rsurface.modelsurfaces + surfacelist[i];
11046 texture = surface->texture;
11047 rsurface.texture = R_GetCurrentTexture(texture);
11048 rsurface.lightmaptexture = NULL;
11049 rsurface.deluxemaptexture = NULL;
11050 rsurface.uselightmaptexture = false;
11051 // scan ahead until we find a different texture
11052 endsurface = min(i + 1024, numsurfaces);
11053 texturenumsurfaces = 0;
11054 texturesurfacelist[texturenumsurfaces++] = surface;
11055 for (;j < endsurface;j++)
11057 surface = rsurface.modelsurfaces + surfacelist[j];
11058 if (texture != surface->texture)
11060 texturesurfacelist[texturenumsurfaces++] = surface;
11062 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11064 // render the range of surfaces as depth
11068 GL_ColorMask(0,0,0,0);
11070 GL_DepthTest(true);
11071 GL_BlendFunc(GL_ONE, GL_ZERO);
11072 GL_DepthMask(true);
11073 // R_Mesh_ResetTextureState();
11075 RSurf_SetupDepthAndCulling();
11076 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11077 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11078 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11082 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11085 for (i = 0;i < numsurfaces;i = j)
11088 surface = rsurface.modelsurfaces + surfacelist[i];
11089 texture = surface->texture;
11090 rsurface.texture = R_GetCurrentTexture(texture);
11091 // scan ahead until we find a different texture
11092 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11093 texturenumsurfaces = 0;
11094 texturesurfacelist[texturenumsurfaces++] = surface;
11095 if(FAKELIGHT_ENABLED)
11097 rsurface.lightmaptexture = NULL;
11098 rsurface.deluxemaptexture = NULL;
11099 rsurface.uselightmaptexture = false;
11100 for (;j < endsurface;j++)
11102 surface = rsurface.modelsurfaces + surfacelist[j];
11103 if (texture != surface->texture)
11105 texturesurfacelist[texturenumsurfaces++] = surface;
11110 rsurface.lightmaptexture = surface->lightmaptexture;
11111 rsurface.deluxemaptexture = surface->deluxemaptexture;
11112 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11113 for (;j < endsurface;j++)
11115 surface = rsurface.modelsurfaces + surfacelist[j];
11116 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11118 texturesurfacelist[texturenumsurfaces++] = surface;
11121 // render the range of surfaces
11122 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11124 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11127 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11129 // transparent surfaces get pushed off into the transparent queue
11130 int surfacelistindex;
11131 const msurface_t *surface;
11132 vec3_t tempcenter, center;
11133 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11135 surface = texturesurfacelist[surfacelistindex];
11136 if (r_transparent_sortsurfacesbynearest.integer)
11138 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11139 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11140 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11144 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11145 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11146 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11148 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11149 if (rsurface.entity->transparent_offset) // transparent offset
11151 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11152 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11153 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11155 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);
11159 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11161 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11163 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11165 RSurf_SetupDepthAndCulling();
11166 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11167 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11168 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11172 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11176 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11179 if (!rsurface.texture->currentnumlayers)
11181 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11182 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11184 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11186 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11187 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11188 else if (!rsurface.texture->currentnumlayers)
11190 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11192 // in the deferred case, transparent surfaces were queued during prepass
11193 if (!r_shadow_usingdeferredprepass)
11194 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11198 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11199 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11204 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11207 texture_t *texture;
11208 R_FrameData_SetMark();
11209 // break the surface list down into batches by texture and use of lightmapping
11210 for (i = 0;i < numsurfaces;i = j)
11213 // texture is the base texture pointer, rsurface.texture is the
11214 // current frame/skin the texture is directing us to use (for example
11215 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11216 // use skin 1 instead)
11217 texture = surfacelist[i]->texture;
11218 rsurface.texture = R_GetCurrentTexture(texture);
11219 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11221 // if this texture is not the kind we want, skip ahead to the next one
11222 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11226 if(FAKELIGHT_ENABLED || depthonly || prepass)
11228 rsurface.lightmaptexture = NULL;
11229 rsurface.deluxemaptexture = NULL;
11230 rsurface.uselightmaptexture = false;
11231 // simply scan ahead until we find a different texture or lightmap state
11232 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11237 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11238 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11239 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11240 // simply scan ahead until we find a different texture or lightmap state
11241 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11244 // render the range of surfaces
11245 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11247 R_FrameData_ReturnToMark();
11250 float locboxvertex3f[6*4*3] =
11252 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11253 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11254 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11255 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11256 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11257 1,0,0, 0,0,0, 0,1,0, 1,1,0
11260 unsigned short locboxelements[6*2*3] =
11265 12,13,14, 12,14,15,
11266 16,17,18, 16,18,19,
11270 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11273 cl_locnode_t *loc = (cl_locnode_t *)ent;
11275 float vertex3f[6*4*3];
11277 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11278 GL_DepthMask(false);
11279 GL_DepthRange(0, 1);
11280 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11281 GL_DepthTest(true);
11282 GL_CullFace(GL_NONE);
11283 R_EntityMatrix(&identitymatrix);
11285 // R_Mesh_ResetTextureState();
11287 i = surfacelist[0];
11288 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11289 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11290 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11291 surfacelist[0] < 0 ? 0.5f : 0.125f);
11293 if (VectorCompare(loc->mins, loc->maxs))
11295 VectorSet(size, 2, 2, 2);
11296 VectorMA(loc->mins, -0.5f, size, mins);
11300 VectorCopy(loc->mins, mins);
11301 VectorSubtract(loc->maxs, loc->mins, size);
11304 for (i = 0;i < 6*4*3;)
11305 for (j = 0;j < 3;j++, i++)
11306 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11308 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11309 R_SetupShader_Generic_NoTexture(false, false);
11310 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11313 void R_DrawLocs(void)
11316 cl_locnode_t *loc, *nearestloc;
11318 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11319 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11321 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11322 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11326 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11328 if (decalsystem->decals)
11329 Mem_Free(decalsystem->decals);
11330 memset(decalsystem, 0, sizeof(*decalsystem));
11333 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)
11336 tridecal_t *decals;
11339 // expand or initialize the system
11340 if (decalsystem->maxdecals <= decalsystem->numdecals)
11342 decalsystem_t old = *decalsystem;
11343 qboolean useshortelements;
11344 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11345 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11346 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)));
11347 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11348 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11349 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11350 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11351 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11352 if (decalsystem->numdecals)
11353 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11355 Mem_Free(old.decals);
11356 for (i = 0;i < decalsystem->maxdecals*3;i++)
11357 decalsystem->element3i[i] = i;
11358 if (useshortelements)
11359 for (i = 0;i < decalsystem->maxdecals*3;i++)
11360 decalsystem->element3s[i] = i;
11363 // grab a decal and search for another free slot for the next one
11364 decals = decalsystem->decals;
11365 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11366 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11368 decalsystem->freedecal = i;
11369 if (decalsystem->numdecals <= i)
11370 decalsystem->numdecals = i + 1;
11372 // initialize the decal
11374 decal->triangleindex = triangleindex;
11375 decal->surfaceindex = surfaceindex;
11376 decal->decalsequence = decalsequence;
11377 decal->color4f[0][0] = c0[0];
11378 decal->color4f[0][1] = c0[1];
11379 decal->color4f[0][2] = c0[2];
11380 decal->color4f[0][3] = 1;
11381 decal->color4f[1][0] = c1[0];
11382 decal->color4f[1][1] = c1[1];
11383 decal->color4f[1][2] = c1[2];
11384 decal->color4f[1][3] = 1;
11385 decal->color4f[2][0] = c2[0];
11386 decal->color4f[2][1] = c2[1];
11387 decal->color4f[2][2] = c2[2];
11388 decal->color4f[2][3] = 1;
11389 decal->vertex3f[0][0] = v0[0];
11390 decal->vertex3f[0][1] = v0[1];
11391 decal->vertex3f[0][2] = v0[2];
11392 decal->vertex3f[1][0] = v1[0];
11393 decal->vertex3f[1][1] = v1[1];
11394 decal->vertex3f[1][2] = v1[2];
11395 decal->vertex3f[2][0] = v2[0];
11396 decal->vertex3f[2][1] = v2[1];
11397 decal->vertex3f[2][2] = v2[2];
11398 decal->texcoord2f[0][0] = t0[0];
11399 decal->texcoord2f[0][1] = t0[1];
11400 decal->texcoord2f[1][0] = t1[0];
11401 decal->texcoord2f[1][1] = t1[1];
11402 decal->texcoord2f[2][0] = t2[0];
11403 decal->texcoord2f[2][1] = t2[1];
11404 TriangleNormal(v0, v1, v2, decal->plane);
11405 VectorNormalize(decal->plane);
11406 decal->plane[3] = DotProduct(v0, decal->plane);
11409 extern cvar_t cl_decals_bias;
11410 extern cvar_t cl_decals_models;
11411 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11412 // baseparms, parms, temps
11413 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)
11418 const float *vertex3f;
11419 const float *normal3f;
11421 float points[2][9][3];
11428 e = rsurface.modelelement3i + 3*triangleindex;
11430 vertex3f = rsurface.modelvertex3f;
11431 normal3f = rsurface.modelnormal3f;
11435 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11437 index = 3*e[cornerindex];
11438 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11443 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11445 index = 3*e[cornerindex];
11446 VectorCopy(vertex3f + index, v[cornerindex]);
11451 //TriangleNormal(v[0], v[1], v[2], normal);
11452 //if (DotProduct(normal, localnormal) < 0.0f)
11454 // clip by each of the box planes formed from the projection matrix
11455 // if anything survives, we emit the decal
11456 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]);
11459 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]);
11462 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]);
11465 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]);
11468 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]);
11471 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]);
11474 // some part of the triangle survived, so we have to accept it...
11477 // dynamic always uses the original triangle
11479 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11481 index = 3*e[cornerindex];
11482 VectorCopy(vertex3f + index, v[cornerindex]);
11485 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11487 // convert vertex positions to texcoords
11488 Matrix4x4_Transform(projection, v[cornerindex], temp);
11489 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11490 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11491 // calculate distance fade from the projection origin
11492 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11493 f = bound(0.0f, f, 1.0f);
11494 c[cornerindex][0] = r * f;
11495 c[cornerindex][1] = g * f;
11496 c[cornerindex][2] = b * f;
11497 c[cornerindex][3] = 1.0f;
11498 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11501 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);
11503 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11504 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);
11506 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)
11508 matrix4x4_t projection;
11509 decalsystem_t *decalsystem;
11512 const msurface_t *surface;
11513 const msurface_t *surfaces;
11514 const int *surfacelist;
11515 const texture_t *texture;
11517 int numsurfacelist;
11518 int surfacelistindex;
11521 float localorigin[3];
11522 float localnormal[3];
11523 float localmins[3];
11524 float localmaxs[3];
11527 float planes[6][4];
11530 int bih_triangles_count;
11531 int bih_triangles[256];
11532 int bih_surfaces[256];
11534 decalsystem = &ent->decalsystem;
11535 model = ent->model;
11536 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11538 R_DecalSystem_Reset(&ent->decalsystem);
11542 if (!model->brush.data_leafs && !cl_decals_models.integer)
11544 if (decalsystem->model)
11545 R_DecalSystem_Reset(decalsystem);
11549 if (decalsystem->model != model)
11550 R_DecalSystem_Reset(decalsystem);
11551 decalsystem->model = model;
11553 RSurf_ActiveModelEntity(ent, true, false, false);
11555 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11556 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11557 VectorNormalize(localnormal);
11558 localsize = worldsize*rsurface.inversematrixscale;
11559 localmins[0] = localorigin[0] - localsize;
11560 localmins[1] = localorigin[1] - localsize;
11561 localmins[2] = localorigin[2] - localsize;
11562 localmaxs[0] = localorigin[0] + localsize;
11563 localmaxs[1] = localorigin[1] + localsize;
11564 localmaxs[2] = localorigin[2] + localsize;
11566 //VectorCopy(localnormal, planes[4]);
11567 //VectorVectors(planes[4], planes[2], planes[0]);
11568 AnglesFromVectors(angles, localnormal, NULL, false);
11569 AngleVectors(angles, planes[0], planes[2], planes[4]);
11570 VectorNegate(planes[0], planes[1]);
11571 VectorNegate(planes[2], planes[3]);
11572 VectorNegate(planes[4], planes[5]);
11573 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11574 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11575 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11576 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11577 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11578 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11583 matrix4x4_t forwardprojection;
11584 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11585 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11590 float projectionvector[4][3];
11591 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11592 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11593 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11594 projectionvector[0][0] = planes[0][0] * ilocalsize;
11595 projectionvector[0][1] = planes[1][0] * ilocalsize;
11596 projectionvector[0][2] = planes[2][0] * ilocalsize;
11597 projectionvector[1][0] = planes[0][1] * ilocalsize;
11598 projectionvector[1][1] = planes[1][1] * ilocalsize;
11599 projectionvector[1][2] = planes[2][1] * ilocalsize;
11600 projectionvector[2][0] = planes[0][2] * ilocalsize;
11601 projectionvector[2][1] = planes[1][2] * ilocalsize;
11602 projectionvector[2][2] = planes[2][2] * ilocalsize;
11603 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11604 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11605 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11606 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11610 dynamic = model->surfmesh.isanimated;
11611 numsurfacelist = model->nummodelsurfaces;
11612 surfacelist = model->sortedmodelsurfaces;
11613 surfaces = model->data_surfaces;
11616 bih_triangles_count = -1;
11619 if(model->render_bih.numleafs)
11620 bih = &model->render_bih;
11621 else if(model->collision_bih.numleafs)
11622 bih = &model->collision_bih;
11625 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11626 if(bih_triangles_count == 0)
11628 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11630 if(bih_triangles_count > 0)
11632 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11634 surfaceindex = bih_surfaces[triangleindex];
11635 surface = surfaces + surfaceindex;
11636 texture = surface->texture;
11637 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11639 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11641 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11646 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11648 surfaceindex = surfacelist[surfacelistindex];
11649 surface = surfaces + surfaceindex;
11650 // check cull box first because it rejects more than any other check
11651 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11653 // skip transparent surfaces
11654 texture = surface->texture;
11655 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11657 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11659 numtriangles = surface->num_triangles;
11660 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11661 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11666 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11667 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)
11669 int renderentityindex;
11670 float worldmins[3];
11671 float worldmaxs[3];
11672 entity_render_t *ent;
11674 if (!cl_decals_newsystem.integer)
11677 worldmins[0] = worldorigin[0] - worldsize;
11678 worldmins[1] = worldorigin[1] - worldsize;
11679 worldmins[2] = worldorigin[2] - worldsize;
11680 worldmaxs[0] = worldorigin[0] + worldsize;
11681 worldmaxs[1] = worldorigin[1] + worldsize;
11682 worldmaxs[2] = worldorigin[2] + worldsize;
11684 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11686 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11688 ent = r_refdef.scene.entities[renderentityindex];
11689 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11692 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11696 typedef struct r_decalsystem_splatqueue_s
11698 vec3_t worldorigin;
11699 vec3_t worldnormal;
11703 unsigned int decalsequence;
11705 r_decalsystem_splatqueue_t;
11707 int r_decalsystem_numqueued = 0;
11708 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11710 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)
11712 r_decalsystem_splatqueue_t *queue;
11714 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11717 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11718 VectorCopy(worldorigin, queue->worldorigin);
11719 VectorCopy(worldnormal, queue->worldnormal);
11720 Vector4Set(queue->color, r, g, b, a);
11721 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11722 queue->worldsize = worldsize;
11723 queue->decalsequence = cl.decalsequence++;
11726 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11729 r_decalsystem_splatqueue_t *queue;
11731 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11732 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);
11733 r_decalsystem_numqueued = 0;
11736 extern cvar_t cl_decals_max;
11737 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11740 decalsystem_t *decalsystem = &ent->decalsystem;
11742 unsigned int killsequence;
11747 if (!decalsystem->numdecals)
11750 if (r_showsurfaces.integer)
11753 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11755 R_DecalSystem_Reset(decalsystem);
11759 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11760 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11762 if (decalsystem->lastupdatetime)
11763 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11766 decalsystem->lastupdatetime = r_refdef.scene.time;
11767 numdecals = decalsystem->numdecals;
11769 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11771 if (decal->color4f[0][3])
11773 decal->lived += frametime;
11774 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11776 memset(decal, 0, sizeof(*decal));
11777 if (decalsystem->freedecal > i)
11778 decalsystem->freedecal = i;
11782 decal = decalsystem->decals;
11783 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11786 // collapse the array by shuffling the tail decals into the gaps
11789 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11790 decalsystem->freedecal++;
11791 if (decalsystem->freedecal == numdecals)
11793 decal[decalsystem->freedecal] = decal[--numdecals];
11796 decalsystem->numdecals = numdecals;
11798 if (numdecals <= 0)
11800 // if there are no decals left, reset decalsystem
11801 R_DecalSystem_Reset(decalsystem);
11805 extern skinframe_t *decalskinframe;
11806 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11809 decalsystem_t *decalsystem = &ent->decalsystem;
11818 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11821 numdecals = decalsystem->numdecals;
11825 if (r_showsurfaces.integer)
11828 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11830 R_DecalSystem_Reset(decalsystem);
11834 // if the model is static it doesn't matter what value we give for
11835 // wantnormals and wanttangents, so this logic uses only rules applicable
11836 // to a model, knowing that they are meaningless otherwise
11837 RSurf_ActiveModelEntity(ent, false, false, false);
11839 decalsystem->lastupdatetime = r_refdef.scene.time;
11841 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11843 // update vertex positions for animated models
11844 v3f = decalsystem->vertex3f;
11845 c4f = decalsystem->color4f;
11846 t2f = decalsystem->texcoord2f;
11847 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11849 if (!decal->color4f[0][3])
11852 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11856 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11859 // update color values for fading decals
11860 if (decal->lived >= cl_decals_time.value)
11861 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11865 c4f[ 0] = decal->color4f[0][0] * alpha;
11866 c4f[ 1] = decal->color4f[0][1] * alpha;
11867 c4f[ 2] = decal->color4f[0][2] * alpha;
11869 c4f[ 4] = decal->color4f[1][0] * alpha;
11870 c4f[ 5] = decal->color4f[1][1] * alpha;
11871 c4f[ 6] = decal->color4f[1][2] * alpha;
11873 c4f[ 8] = decal->color4f[2][0] * alpha;
11874 c4f[ 9] = decal->color4f[2][1] * alpha;
11875 c4f[10] = decal->color4f[2][2] * alpha;
11878 t2f[0] = decal->texcoord2f[0][0];
11879 t2f[1] = decal->texcoord2f[0][1];
11880 t2f[2] = decal->texcoord2f[1][0];
11881 t2f[3] = decal->texcoord2f[1][1];
11882 t2f[4] = decal->texcoord2f[2][0];
11883 t2f[5] = decal->texcoord2f[2][1];
11885 // update vertex positions for animated models
11886 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11888 e = rsurface.modelelement3i + 3*decal->triangleindex;
11889 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11890 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11891 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11895 VectorCopy(decal->vertex3f[0], v3f);
11896 VectorCopy(decal->vertex3f[1], v3f + 3);
11897 VectorCopy(decal->vertex3f[2], v3f + 6);
11900 if (r_refdef.fogenabled)
11902 alpha = RSurf_FogVertex(v3f);
11903 VectorScale(c4f, alpha, c4f);
11904 alpha = RSurf_FogVertex(v3f + 3);
11905 VectorScale(c4f + 4, alpha, c4f + 4);
11906 alpha = RSurf_FogVertex(v3f + 6);
11907 VectorScale(c4f + 8, alpha, c4f + 8);
11918 r_refdef.stats[r_stat_drawndecals] += numtris;
11920 // now render the decals all at once
11921 // (this assumes they all use one particle font texture!)
11922 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);
11923 // R_Mesh_ResetTextureState();
11924 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11925 GL_DepthMask(false);
11926 GL_DepthRange(0, 1);
11927 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11928 GL_DepthTest(true);
11929 GL_CullFace(GL_NONE);
11930 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11931 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11932 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11936 static void R_DrawModelDecals(void)
11940 // fade faster when there are too many decals
11941 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11942 for (i = 0;i < r_refdef.scene.numentities;i++)
11943 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11945 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11946 for (i = 0;i < r_refdef.scene.numentities;i++)
11947 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11948 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11950 R_DecalSystem_ApplySplatEntitiesQueue();
11952 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11953 for (i = 0;i < r_refdef.scene.numentities;i++)
11954 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11956 r_refdef.stats[r_stat_totaldecals] += numdecals;
11958 if (r_showsurfaces.integer)
11961 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11963 for (i = 0;i < r_refdef.scene.numentities;i++)
11965 if (!r_refdef.viewcache.entityvisible[i])
11967 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11968 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11972 extern cvar_t mod_collision_bih;
11973 static void R_DrawDebugModel(void)
11975 entity_render_t *ent = rsurface.entity;
11976 int i, j, flagsmask;
11977 const msurface_t *surface;
11978 dp_model_t *model = ent->model;
11980 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11983 if (r_showoverdraw.value > 0)
11985 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11986 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11987 R_SetupShader_Generic_NoTexture(false, false);
11988 GL_DepthTest(false);
11989 GL_DepthMask(false);
11990 GL_DepthRange(0, 1);
11991 GL_BlendFunc(GL_ONE, GL_ONE);
11992 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11994 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11996 rsurface.texture = R_GetCurrentTexture(surface->texture);
11997 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11999 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12000 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12001 if (!rsurface.texture->currentlayers->depthmask)
12002 GL_Color(c, 0, 0, 1.0f);
12003 else if (ent == r_refdef.scene.worldentity)
12004 GL_Color(c, c, c, 1.0f);
12006 GL_Color(0, c, 0, 1.0f);
12007 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12011 rsurface.texture = NULL;
12014 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12016 // R_Mesh_ResetTextureState();
12017 R_SetupShader_Generic_NoTexture(false, false);
12018 GL_DepthRange(0, 1);
12019 GL_DepthTest(!r_showdisabledepthtest.integer);
12020 GL_DepthMask(false);
12021 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12023 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12027 qboolean cullbox = false;
12028 const q3mbrush_t *brush;
12029 const bih_t *bih = &model->collision_bih;
12030 const bih_leaf_t *bihleaf;
12031 float vertex3f[3][3];
12032 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12033 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12035 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12037 switch (bihleaf->type)
12040 brush = model->brush.data_brushes + bihleaf->itemindex;
12041 if (brush->colbrushf && brush->colbrushf->numtriangles)
12043 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);
12044 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12045 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12048 case BIH_COLLISIONTRIANGLE:
12049 triangleindex = bihleaf->itemindex;
12050 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12051 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12052 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12053 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);
12054 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12055 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12057 case BIH_RENDERTRIANGLE:
12058 triangleindex = bihleaf->itemindex;
12059 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12060 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12061 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12062 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);
12063 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12064 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12070 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12073 if (r_showtris.value > 0 && qglPolygonMode)
12075 if (r_showdisabledepthtest.integer)
12077 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12078 GL_DepthMask(false);
12082 GL_BlendFunc(GL_ONE, GL_ZERO);
12083 GL_DepthMask(true);
12085 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12086 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12088 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12090 rsurface.texture = R_GetCurrentTexture(surface->texture);
12091 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12093 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12094 if (!rsurface.texture->currentlayers->depthmask)
12095 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12096 else if (ent == r_refdef.scene.worldentity)
12097 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12099 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12100 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12104 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12105 rsurface.texture = NULL;
12108 if (r_shownormals.value != 0 && qglBegin)
12112 if (r_showdisabledepthtest.integer)
12114 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12115 GL_DepthMask(false);
12119 GL_BlendFunc(GL_ONE, GL_ZERO);
12120 GL_DepthMask(true);
12122 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12124 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12126 rsurface.texture = R_GetCurrentTexture(surface->texture);
12127 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12129 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12130 qglBegin(GL_LINES);
12131 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12133 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12135 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12136 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12137 qglVertex3f(v[0], v[1], v[2]);
12138 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12139 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12140 qglVertex3f(v[0], v[1], v[2]);
12143 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12145 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12147 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12148 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12149 qglVertex3f(v[0], v[1], v[2]);
12150 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12151 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12152 qglVertex3f(v[0], v[1], v[2]);
12155 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12157 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12159 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12160 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12161 qglVertex3f(v[0], v[1], v[2]);
12162 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12163 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12164 qglVertex3f(v[0], v[1], v[2]);
12167 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12169 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12171 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12172 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12173 qglVertex3f(v[0], v[1], v[2]);
12174 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12175 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12176 qglVertex3f(v[0], v[1], v[2]);
12183 rsurface.texture = NULL;
12188 int r_maxsurfacelist = 0;
12189 const msurface_t **r_surfacelist = NULL;
12190 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12192 int i, j, endj, flagsmask;
12193 dp_model_t *model = ent->model;
12194 msurface_t *surfaces;
12195 unsigned char *update;
12196 int numsurfacelist = 0;
12200 if (r_maxsurfacelist < model->num_surfaces)
12202 r_maxsurfacelist = model->num_surfaces;
12204 Mem_Free((msurface_t **)r_surfacelist);
12205 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12208 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12209 RSurf_ActiveModelEntity(ent, false, false, false);
12211 RSurf_ActiveModelEntity(ent, true, true, true);
12212 else if (depthonly)
12214 switch (vid.renderpath)
12216 case RENDERPATH_GL20:
12217 case RENDERPATH_D3D9:
12218 case RENDERPATH_D3D10:
12219 case RENDERPATH_D3D11:
12220 case RENDERPATH_SOFT:
12221 case RENDERPATH_GLES2:
12222 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12224 case RENDERPATH_GL11:
12225 case RENDERPATH_GL13:
12226 case RENDERPATH_GLES1:
12227 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12233 switch (vid.renderpath)
12235 case RENDERPATH_GL20:
12236 case RENDERPATH_D3D9:
12237 case RENDERPATH_D3D10:
12238 case RENDERPATH_D3D11:
12239 case RENDERPATH_SOFT:
12240 case RENDERPATH_GLES2:
12241 RSurf_ActiveModelEntity(ent, true, true, false);
12243 case RENDERPATH_GL11:
12244 case RENDERPATH_GL13:
12245 case RENDERPATH_GLES1:
12246 RSurf_ActiveModelEntity(ent, true, false, false);
12251 surfaces = model->data_surfaces;
12252 update = model->brushq1.lightmapupdateflags;
12254 // update light styles
12255 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12257 model_brush_lightstyleinfo_t *style;
12258 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12260 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12262 int *list = style->surfacelist;
12263 style->value = r_refdef.scene.lightstylevalue[style->style];
12264 for (j = 0;j < style->numsurfaces;j++)
12265 update[list[j]] = true;
12270 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12274 R_DrawDebugModel();
12275 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12279 rsurface.lightmaptexture = NULL;
12280 rsurface.deluxemaptexture = NULL;
12281 rsurface.uselightmaptexture = false;
12282 rsurface.texture = NULL;
12283 rsurface.rtlight = NULL;
12284 numsurfacelist = 0;
12285 // add visible surfaces to draw list
12286 if (ent == r_refdef.scene.worldentity)
12288 // for the world entity, check surfacevisible
12289 for (i = 0;i < model->nummodelsurfaces;i++)
12291 j = model->sortedmodelsurfaces[i];
12292 if (r_refdef.viewcache.world_surfacevisible[j])
12293 r_surfacelist[numsurfacelist++] = surfaces + j;
12298 // add all surfaces
12299 for (i = 0; i < model->nummodelsurfaces; i++)
12300 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12302 // don't do anything if there were no surfaces
12303 if (!numsurfacelist)
12305 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12308 // update lightmaps if needed
12312 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12317 R_BuildLightMap(ent, surfaces + j);
12322 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12324 // add to stats if desired
12325 if (r_speeds.integer && !skysurfaces && !depthonly)
12327 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12328 for (j = 0;j < numsurfacelist;j++)
12329 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12332 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12335 void R_DebugLine(vec3_t start, vec3_t end)
12337 dp_model_t *mod = CL_Mesh_UI();
12339 int e0, e1, e2, e3;
12340 float offsetx, offsety, x1, y1, x2, y2, width = 1.0f;
12341 float r1 = 1.0f, g1 = 0.0f, b1 = 0.0f, alpha1 = 0.25f;
12342 float r2 = 1.0f, g2 = 1.0f, b2 = 0.0f, alpha2 = 0.25f;
12345 // transform to screen coords first
12346 Vector4Set(w[0], start[0], start[1], start[2], 1);
12347 Vector4Set(w[1], end[0], end[1], end[2], 1);
12348 R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[0], s[0]);
12349 R_Viewport_TransformToScreen(&r_refdef.view.viewport, w[1], s[1]);
12350 x1 = s[0][0] * vid_conwidth.value / vid.width;
12351 y1 = (vid.height - s[0][1]) * vid_conheight.value / vid.height;
12352 x2 = s[1][0] * vid_conwidth.value / vid.width;
12353 y2 = (vid.height - s[1][1]) * vid_conheight.value / vid.height;
12354 //Con_DPrintf("R_DebugLine: %.0f,%.0f to %.0f,%.0f\n", x1, y1, x2, y2);
12356 // add the line to the UI mesh for drawing later
12358 // width is measured in real pixels
12359 if (fabs(x2 - x1) > fabs(y2 - y1))
12362 offsety = 0.5f * width * vid_conheight.value / vid.height;
12366 offsetx = 0.5f * width * vid_conwidth.value / vid.width;
12369 surf = Mod_Mesh_AddSurface(mod, Mod_Mesh_GetTexture(mod, "white", 0, 0, MATERIALFLAG_VERTEXCOLOR), true);
12370 e0 = Mod_Mesh_IndexForVertex(mod, surf, x1 - offsetx, y1 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
12371 e1 = Mod_Mesh_IndexForVertex(mod, surf, x2 - offsetx, y2 - offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
12372 e2 = Mod_Mesh_IndexForVertex(mod, surf, x2 + offsetx, y2 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r2, g2, b2, alpha2);
12373 e3 = Mod_Mesh_IndexForVertex(mod, surf, x1 + offsetx, y1 + offsety, 10, 0, 0, -1, 0, 0, 0, 0, r1, g1, b1, alpha1);
12374 Mod_Mesh_AddTriangle(mod, surf, e0, e1, e2);
12375 Mod_Mesh_AddTriangle(mod, surf, e0, e2, e3);
12380 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12383 static texture_t texture;
12384 static msurface_t surface;
12385 const msurface_t *surfacelist = &surface;
12387 // fake enough texture and surface state to render this geometry
12389 texture.update_lastrenderframe = -1; // regenerate this texture
12390 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12391 texture.basealpha = 1.0f;
12392 texture.currentskinframe = skinframe;
12393 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12394 texture.offsetmapping = OFFSETMAPPING_OFF;
12395 texture.offsetscale = 1;
12396 texture.specularscalemod = 1;
12397 texture.specularpowermod = 1;
12398 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12399 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12400 // JUST GREP FOR "specularscalemod = 1".
12402 for (q = 0; q < 3; q++)
12404 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12405 texture.render_modellight_lightdir[q] = q == 2;
12406 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12407 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12408 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12409 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12410 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12411 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12412 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12413 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12415 texture.currentalpha = 1.0f;
12417 surface.texture = &texture;
12418 surface.num_triangles = numtriangles;
12419 surface.num_firsttriangle = firsttriangle;
12420 surface.num_vertices = numvertices;
12421 surface.num_firstvertex = firstvertex;
12424 rsurface.texture = R_GetCurrentTexture(surface.texture);
12425 rsurface.lightmaptexture = NULL;
12426 rsurface.deluxemaptexture = NULL;
12427 rsurface.uselightmaptexture = false;
12428 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12431 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)
12433 static msurface_t surface;
12434 const msurface_t *surfacelist = &surface;
12436 // fake enough texture and surface state to render this geometry
12437 surface.texture = texture;
12438 surface.num_triangles = numtriangles;
12439 surface.num_firsttriangle = firsttriangle;
12440 surface.num_vertices = numvertices;
12441 surface.num_firstvertex = firstvertex;
12444 rsurface.texture = R_GetCurrentTexture(surface.texture);
12445 rsurface.lightmaptexture = NULL;
12446 rsurface.deluxemaptexture = NULL;
12447 rsurface.uselightmaptexture = false;
12448 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);