2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
66 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!"};
67 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!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 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)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 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"};
73 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"};
74 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"};
75 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"};
76 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"};
77 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"};
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 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)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
85 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"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 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"};
93 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"};
94 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"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
97 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%)" };
98 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)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 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"};
102 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"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 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"};
105 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"};
106 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"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 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)"};
116 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)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 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"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
128 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"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 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"};
132 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"};
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 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."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 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."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 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."};
145 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."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 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"};
148 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"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 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"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 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
159 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
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
170 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)"};
171 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"};
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
177 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"};
178 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"};
179 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"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 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"};
183 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)"};
184 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)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 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)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 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)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 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)"};
193 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)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 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"};
196 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."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
207 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)"};
208 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)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 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"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 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"};
215 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"};
216 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
244 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"};
246 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"};
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
252 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)"};
253 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)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 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"};
260 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."};
262 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)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
265 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
271 extern cvar_t v_glslgamma_2d;
273 extern qboolean v_flipped_state;
275 r_framebufferstate_t r_fb;
277 /// shadow volume bsp struct with automatically growing nodes buffer
280 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
282 rtexture_t *r_texture_blanknormalmap;
283 rtexture_t *r_texture_white;
284 rtexture_t *r_texture_grey128;
285 rtexture_t *r_texture_black;
286 rtexture_t *r_texture_notexture;
287 rtexture_t *r_texture_whitecube;
288 rtexture_t *r_texture_normalizationcube;
289 rtexture_t *r_texture_fogattenuation;
290 rtexture_t *r_texture_fogheighttexture;
291 rtexture_t *r_texture_gammaramps;
292 unsigned int r_texture_gammaramps_serial;
293 //rtexture_t *r_texture_fogintensity;
294 rtexture_t *r_texture_reflectcube;
296 // TODO: hash lookups?
297 typedef struct cubemapinfo_s
304 int r_texture_numcubemaps;
305 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
307 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
308 unsigned int r_numqueries;
309 unsigned int r_maxqueries;
311 typedef struct r_qwskincache_s
313 char name[MAX_QPATH];
314 skinframe_t *skinframe;
318 static r_qwskincache_t *r_qwskincache;
319 static int r_qwskincache_size;
321 /// vertex coordinates for a quad that covers the screen exactly
322 extern const float r_screenvertex3f[12];
323 extern const float r_d3dscreenvertex3f[12];
324 const float r_screenvertex3f[12] =
331 const float r_d3dscreenvertex3f[12] =
339 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
342 for (i = 0;i < verts;i++)
353 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
356 for (i = 0;i < verts;i++)
366 // FIXME: move this to client?
369 if (gamemode == GAME_NEHAHRA)
371 Cvar_Set("gl_fogenable", "0");
372 Cvar_Set("gl_fogdensity", "0.2");
373 Cvar_Set("gl_fogred", "0.3");
374 Cvar_Set("gl_foggreen", "0.3");
375 Cvar_Set("gl_fogblue", "0.3");
377 r_refdef.fog_density = 0;
378 r_refdef.fog_red = 0;
379 r_refdef.fog_green = 0;
380 r_refdef.fog_blue = 0;
381 r_refdef.fog_alpha = 1;
382 r_refdef.fog_start = 0;
383 r_refdef.fog_end = 16384;
384 r_refdef.fog_height = 1<<30;
385 r_refdef.fog_fadedepth = 128;
386 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
389 static void R_BuildBlankTextures(void)
391 unsigned char data[4];
392 data[2] = 128; // normal X
393 data[1] = 128; // normal Y
394 data[0] = 255; // normal Z
395 data[3] = 255; // height
396 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
406 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
411 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
414 static void R_BuildNoTexture(void)
417 unsigned char pix[16][16][4];
418 // this makes a light grey/dark grey checkerboard texture
419 for (y = 0;y < 16;y++)
421 for (x = 0;x < 16;x++)
423 if ((y < 8) ^ (x < 8))
439 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
442 static void R_BuildWhiteCube(void)
444 unsigned char data[6*1*1*4];
445 memset(data, 255, sizeof(data));
446 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
449 static void R_BuildNormalizationCube(void)
453 vec_t s, t, intensity;
456 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
457 for (side = 0;side < 6;side++)
459 for (y = 0;y < NORMSIZE;y++)
461 for (x = 0;x < NORMSIZE;x++)
463 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
464 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
499 intensity = 127.0f / sqrt(DotProduct(v, v));
500 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
501 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
502 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
503 data[((side*64+y)*64+x)*4+3] = 255;
507 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
511 static void R_BuildFogTexture(void)
515 unsigned char data1[FOGWIDTH][4];
516 //unsigned char data2[FOGWIDTH][4];
519 r_refdef.fogmasktable_start = r_refdef.fog_start;
520 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
521 r_refdef.fogmasktable_range = r_refdef.fogrange;
522 r_refdef.fogmasktable_density = r_refdef.fog_density;
524 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
525 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
527 d = (x * r - r_refdef.fogmasktable_start);
528 if(developer_extra.integer)
529 Con_DPrintf("%f ", d);
531 if (r_fog_exp2.integer)
532 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
534 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
535 if(developer_extra.integer)
536 Con_DPrintf(" : %f ", alpha);
537 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
538 if(developer_extra.integer)
539 Con_DPrintf(" = %f\n", alpha);
540 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
543 for (x = 0;x < FOGWIDTH;x++)
545 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
550 //data2[x][0] = 255 - b;
551 //data2[x][1] = 255 - b;
552 //data2[x][2] = 255 - b;
555 if (r_texture_fogattenuation)
557 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
558 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
562 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
563 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
567 static void R_BuildFogHeightTexture(void)
569 unsigned char *inpixels;
577 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
578 if (r_refdef.fogheighttexturename[0])
579 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
582 r_refdef.fog_height_tablesize = 0;
583 if (r_texture_fogheighttexture)
584 R_FreeTexture(r_texture_fogheighttexture);
585 r_texture_fogheighttexture = NULL;
586 if (r_refdef.fog_height_table2d)
587 Mem_Free(r_refdef.fog_height_table2d);
588 r_refdef.fog_height_table2d = NULL;
589 if (r_refdef.fog_height_table1d)
590 Mem_Free(r_refdef.fog_height_table1d);
591 r_refdef.fog_height_table1d = NULL;
595 r_refdef.fog_height_tablesize = size;
596 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
597 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
598 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
600 // LordHavoc: now the magic - what is that table2d for? it is a cooked
601 // average fog color table accounting for every fog layer between a point
602 // and the camera. (Note: attenuation is handled separately!)
603 for (y = 0;y < size;y++)
605 for (x = 0;x < size;x++)
611 for (j = x;j <= y;j++)
613 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
619 for (j = x;j >= y;j--)
621 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
626 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
627 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
628 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
629 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
632 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
635 //=======================================================================================================================================================
637 static const char *builtinshaderstrings[] =
639 #include "shader_glsl.h"
643 const char *builtinhlslshaderstrings[] =
645 #include "shader_hlsl.h"
649 //=======================================================================================================================================================
651 typedef struct shaderpermutationinfo_s
656 shaderpermutationinfo_t;
658 typedef struct shadermodeinfo_s
660 const char *sourcebasename;
661 const char *extension;
662 const char **builtinshaderstrings;
671 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
672 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
674 {"#define USEDIFFUSE\n", " diffuse"},
675 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
676 {"#define USEVIEWTINT\n", " viewtint"},
677 {"#define USECOLORMAPPING\n", " colormapping"},
678 {"#define USESATURATION\n", " saturation"},
679 {"#define USEFOGINSIDE\n", " foginside"},
680 {"#define USEFOGOUTSIDE\n", " fogoutside"},
681 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
682 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
683 {"#define USEGAMMARAMPS\n", " gammaramps"},
684 {"#define USECUBEFILTER\n", " cubefilter"},
685 {"#define USEGLOW\n", " glow"},
686 {"#define USEBLOOM\n", " bloom"},
687 {"#define USESPECULAR\n", " specular"},
688 {"#define USEPOSTPROCESSING\n", " postprocessing"},
689 {"#define USEREFLECTION\n", " reflection"},
690 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
691 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
692 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
693 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
694 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
695 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
696 {"#define USEALPHAKILL\n", " alphakill"},
697 {"#define USEREFLECTCUBE\n", " reflectcube"},
698 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
699 {"#define USEBOUNCEGRID\n", " bouncegrid"},
700 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
701 {"#define USETRIPPY\n", " trippy"},
702 {"#define USEDEPTHRGB\n", " depthrgb"},
703 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
704 {"#define USESKELETAL\n", " skeletal"},
705 {"#define USEOCCLUDE\n", " occlude"}
708 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
709 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
711 // SHADERLANGUAGE_GLSL
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
721 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
722 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
723 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
724 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
725 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
726 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
727 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
728 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
729 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731 // SHADERLANGUAGE_HLSL
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
741 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
742 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
743 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
744 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
745 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
746 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
747 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
748 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
749 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
753 struct r_glsl_permutation_s;
754 typedef struct r_glsl_permutation_s
757 struct r_glsl_permutation_s *hashnext;
759 dpuint64 permutation;
761 /// indicates if we have tried compiling this permutation already
763 /// 0 if compilation failed
765 // texture units assigned to each detected uniform
766 int tex_Texture_First;
767 int tex_Texture_Second;
768 int tex_Texture_GammaRamps;
769 int tex_Texture_Normal;
770 int tex_Texture_Color;
771 int tex_Texture_Gloss;
772 int tex_Texture_Glow;
773 int tex_Texture_SecondaryNormal;
774 int tex_Texture_SecondaryColor;
775 int tex_Texture_SecondaryGloss;
776 int tex_Texture_SecondaryGlow;
777 int tex_Texture_Pants;
778 int tex_Texture_Shirt;
779 int tex_Texture_FogHeightTexture;
780 int tex_Texture_FogMask;
781 int tex_Texture_Lightmap;
782 int tex_Texture_Deluxemap;
783 int tex_Texture_Attenuation;
784 int tex_Texture_Cube;
785 int tex_Texture_Refraction;
786 int tex_Texture_Reflection;
787 int tex_Texture_ShadowMap2D;
788 int tex_Texture_CubeProjection;
789 int tex_Texture_ScreenNormalMap;
790 int tex_Texture_ScreenDiffuse;
791 int tex_Texture_ScreenSpecular;
792 int tex_Texture_ReflectMask;
793 int tex_Texture_ReflectCube;
794 int tex_Texture_BounceGrid;
795 /// locations of detected uniforms in program object, or -1 if not found
796 int loc_Texture_First;
797 int loc_Texture_Second;
798 int loc_Texture_GammaRamps;
799 int loc_Texture_Normal;
800 int loc_Texture_Color;
801 int loc_Texture_Gloss;
802 int loc_Texture_Glow;
803 int loc_Texture_SecondaryNormal;
804 int loc_Texture_SecondaryColor;
805 int loc_Texture_SecondaryGloss;
806 int loc_Texture_SecondaryGlow;
807 int loc_Texture_Pants;
808 int loc_Texture_Shirt;
809 int loc_Texture_FogHeightTexture;
810 int loc_Texture_FogMask;
811 int loc_Texture_Lightmap;
812 int loc_Texture_Deluxemap;
813 int loc_Texture_Attenuation;
814 int loc_Texture_Cube;
815 int loc_Texture_Refraction;
816 int loc_Texture_Reflection;
817 int loc_Texture_ShadowMap2D;
818 int loc_Texture_CubeProjection;
819 int loc_Texture_ScreenNormalMap;
820 int loc_Texture_ScreenDiffuse;
821 int loc_Texture_ScreenSpecular;
822 int loc_Texture_ReflectMask;
823 int loc_Texture_ReflectCube;
824 int loc_Texture_BounceGrid;
826 int loc_BloomBlur_Parameters;
828 int loc_Color_Ambient;
829 int loc_Color_Diffuse;
830 int loc_Color_Specular;
834 int loc_DeferredColor_Ambient;
835 int loc_DeferredColor_Diffuse;
836 int loc_DeferredColor_Specular;
837 int loc_DeferredMod_Diffuse;
838 int loc_DeferredMod_Specular;
839 int loc_DistortScaleRefractReflect;
842 int loc_FogHeightFade;
844 int loc_FogPlaneViewDist;
845 int loc_FogRangeRecip;
848 int loc_LightPosition;
849 int loc_OffsetMapping_ScaleSteps;
850 int loc_OffsetMapping_LodDistance;
851 int loc_OffsetMapping_Bias;
853 int loc_ReflectColor;
854 int loc_ReflectFactor;
855 int loc_ReflectOffset;
856 int loc_RefractColor;
858 int loc_ScreenCenterRefractReflect;
859 int loc_ScreenScaleRefractReflect;
860 int loc_ScreenToDepth;
861 int loc_ShadowMap_Parameters;
862 int loc_ShadowMap_TextureScale;
863 int loc_SpecularPower;
864 int loc_Skeletal_Transform12;
869 int loc_ViewTintColor;
871 int loc_ModelToLight;
873 int loc_BackgroundTexMatrix;
874 int loc_ModelViewProjectionMatrix;
875 int loc_ModelViewMatrix;
876 int loc_PixelToScreenTexCoord;
877 int loc_ModelToReflectCube;
878 int loc_ShadowMapMatrix;
879 int loc_BloomColorSubtract;
880 int loc_NormalmapScrollBlend;
881 int loc_BounceGridMatrix;
882 int loc_BounceGridIntensity;
883 /// uniform block bindings
884 int ubibind_Skeletal_Transform12_UniformBlock;
885 /// uniform block indices
886 int ubiloc_Skeletal_Transform12_UniformBlock;
888 r_glsl_permutation_t;
890 #define SHADERPERMUTATION_HASHSIZE 256
893 // non-degradable "lightweight" shader parameters to keep the permutations simpler
894 // these can NOT degrade! only use for simple stuff
897 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
898 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
899 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
900 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
901 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
902 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
903 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
904 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
905 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
906 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
907 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
908 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
909 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
910 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
912 #define SHADERSTATICPARMS_COUNT 14
914 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
915 static int shaderstaticparms_count = 0;
917 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
918 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
920 extern qboolean r_shadow_shadowmapsampler;
921 extern int r_shadow_shadowmappcf;
922 qboolean R_CompileShader_CheckStaticParms(void)
924 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
925 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
926 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
929 if (r_glsl_saturation_redcompensate.integer)
930 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
931 if (r_glsl_vertextextureblend_usebothalphas.integer)
932 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
933 if (r_shadow_glossexact.integer)
934 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
935 if (r_glsl_postprocess.integer)
937 if (r_glsl_postprocess_uservec1_enable.integer)
938 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
939 if (r_glsl_postprocess_uservec2_enable.integer)
940 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
941 if (r_glsl_postprocess_uservec3_enable.integer)
942 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
943 if (r_glsl_postprocess_uservec4_enable.integer)
944 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
948 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
949 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
951 if (r_shadow_shadowmapsampler)
952 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
953 if (r_shadow_shadowmappcf > 1)
954 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
955 else if (r_shadow_shadowmappcf)
956 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
957 if (r_celshading.integer)
958 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
959 if (r_celoutlines.integer)
960 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
962 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
965 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
966 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
967 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
969 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
970 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
972 shaderstaticparms_count = 0;
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
980 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
981 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
982 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
983 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
984 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
985 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
986 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
987 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
988 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
991 /// information about each possible shader permutation
992 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
993 /// currently selected permutation
994 r_glsl_permutation_t *r_glsl_permutation;
995 /// storage for permutations linked in the hash table
996 memexpandablearray_t r_glsl_permutationarray;
998 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1000 //unsigned int hashdepth = 0;
1001 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1002 r_glsl_permutation_t *p;
1003 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1005 if (p->mode == mode && p->permutation == permutation)
1007 //if (hashdepth > 10)
1008 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1013 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1015 p->permutation = permutation;
1016 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1017 r_glsl_permutationhash[mode][hashindex] = p;
1018 //if (hashdepth > 10)
1019 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1023 static char *R_ShaderStrCat(const char **strings)
1026 const char **p = strings;
1029 for (p = strings;(t = *p);p++)
1032 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1034 for (p = strings;(t = *p);p++)
1044 static char *R_ShaderStrCat(const char **strings);
1045 static void R_InitShaderModeInfo(void)
1048 shadermodeinfo_t *modeinfo;
1049 // 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)
1050 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1052 for (i = 0; i < SHADERMODE_COUNT; i++)
1054 char filename[MAX_QPATH];
1055 modeinfo = &shadermodeinfo[language][i];
1056 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1057 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1058 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1059 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1064 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1067 // if the mode has no filename we have to return the builtin string
1068 if (builtinonly || !modeinfo->filename)
1069 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1070 // note that FS_LoadFile appends a 0 byte to make it a valid string
1071 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1074 if (printfromdisknotice)
1075 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1076 return shaderstring;
1078 // fall back to builtinstring
1079 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1087 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1089 char permutationname[256];
1090 int vertstrings_count = 0;
1091 int geomstrings_count = 0;
1092 int fragstrings_count = 0;
1093 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1102 permutationname[0] = 0;
1103 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1105 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1107 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108 if(vid.support.glshaderversion >= 140)
1110 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1117 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118 else if(vid.support.glshaderversion >= 130)
1120 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1127 // if we can do #version 120, we should (this adds the invariant keyword)
1128 else if(vid.support.glshaderversion >= 120)
1130 vertstrings_list[vertstrings_count++] = "#version 120\n";
1131 geomstrings_list[geomstrings_count++] = "#version 120\n";
1132 fragstrings_list[fragstrings_count++] = "#version 120\n";
1133 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1134 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1135 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1137 // GLES also adds several things from GLSL120
1138 switch(vid.renderpath)
1140 case RENDERPATH_GLES2:
1141 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1142 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1143 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1149 // the first pretext is which type of shader to compile as
1150 // (later these will all be bound together as a program object)
1151 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1152 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1153 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1155 // the second pretext is the mode (for example a light source)
1156 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1157 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1158 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1159 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1161 // now add all the permutation pretexts
1162 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1164 if (permutation & (1ll<<i))
1166 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1167 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1168 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1169 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1173 // keep line numbers correct
1174 vertstrings_list[vertstrings_count++] = "\n";
1175 geomstrings_list[geomstrings_count++] = "\n";
1176 fragstrings_list[fragstrings_count++] = "\n";
1181 R_CompileShader_AddStaticParms(mode, permutation);
1182 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1183 vertstrings_count += shaderstaticparms_count;
1184 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1185 geomstrings_count += shaderstaticparms_count;
1186 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1187 fragstrings_count += shaderstaticparms_count;
1189 // now append the shader text itself
1190 vertstrings_list[vertstrings_count++] = sourcestring;
1191 geomstrings_list[geomstrings_count++] = sourcestring;
1192 fragstrings_list[fragstrings_count++] = sourcestring;
1194 // compile the shader program
1195 if (vertstrings_count + geomstrings_count + fragstrings_count)
1196 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1200 qglUseProgram(p->program);CHECKGLERROR
1201 // look up all the uniform variable names we care about, so we don't
1202 // have to look them up every time we set them
1207 GLint activeuniformindex = 0;
1208 GLint numactiveuniforms = 0;
1209 char uniformname[128];
1210 GLsizei uniformnamelength = 0;
1211 GLint uniformsize = 0;
1212 GLenum uniformtype = 0;
1213 memset(uniformname, 0, sizeof(uniformname));
1214 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1215 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1216 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1218 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1219 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1224 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1225 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1226 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1227 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1228 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1229 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1230 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1231 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1232 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1233 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1234 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1235 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1236 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1237 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1238 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1239 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1240 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1241 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1242 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1243 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1244 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1245 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1246 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1247 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1248 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1249 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1250 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1251 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1252 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1253 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1254 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1255 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1256 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1257 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1258 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1259 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1260 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1261 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1262 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1263 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1264 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1265 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1266 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1267 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1268 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1269 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1270 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1271 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1272 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1273 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1274 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1275 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1276 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1277 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1278 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1279 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1280 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1281 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1282 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1283 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1284 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1285 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1286 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1287 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1288 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1289 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1290 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1291 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1292 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1293 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1294 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1295 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1296 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1297 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1298 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1299 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1300 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1301 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1302 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1303 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1304 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1305 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1306 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1307 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1308 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1309 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1310 // initialize the samplers to refer to the texture units we use
1311 p->tex_Texture_First = -1;
1312 p->tex_Texture_Second = -1;
1313 p->tex_Texture_GammaRamps = -1;
1314 p->tex_Texture_Normal = -1;
1315 p->tex_Texture_Color = -1;
1316 p->tex_Texture_Gloss = -1;
1317 p->tex_Texture_Glow = -1;
1318 p->tex_Texture_SecondaryNormal = -1;
1319 p->tex_Texture_SecondaryColor = -1;
1320 p->tex_Texture_SecondaryGloss = -1;
1321 p->tex_Texture_SecondaryGlow = -1;
1322 p->tex_Texture_Pants = -1;
1323 p->tex_Texture_Shirt = -1;
1324 p->tex_Texture_FogHeightTexture = -1;
1325 p->tex_Texture_FogMask = -1;
1326 p->tex_Texture_Lightmap = -1;
1327 p->tex_Texture_Deluxemap = -1;
1328 p->tex_Texture_Attenuation = -1;
1329 p->tex_Texture_Cube = -1;
1330 p->tex_Texture_Refraction = -1;
1331 p->tex_Texture_Reflection = -1;
1332 p->tex_Texture_ShadowMap2D = -1;
1333 p->tex_Texture_CubeProjection = -1;
1334 p->tex_Texture_ScreenNormalMap = -1;
1335 p->tex_Texture_ScreenDiffuse = -1;
1336 p->tex_Texture_ScreenSpecular = -1;
1337 p->tex_Texture_ReflectMask = -1;
1338 p->tex_Texture_ReflectCube = -1;
1339 p->tex_Texture_BounceGrid = -1;
1340 // bind the texture samplers in use
1342 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1343 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1344 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1345 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1346 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1347 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1348 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1349 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1350 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1351 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1352 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1353 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1354 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1355 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1356 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1357 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1358 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1359 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1360 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1361 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1362 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1363 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1364 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1365 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1366 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1367 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1368 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1369 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1370 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1371 // get the uniform block indices so we can bind them
1372 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1373 if (vid.support.arb_uniform_buffer_object)
1374 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1377 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1378 // clear the uniform block bindings
1379 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1380 // bind the uniform blocks in use
1382 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1383 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1385 // we're done compiling and setting up the shader, at least until it is used
1387 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1390 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1394 Mem_Free(sourcestring);
1397 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1399 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1400 if (r_glsl_permutation != perm)
1402 r_glsl_permutation = perm;
1403 if (!r_glsl_permutation->program)
1405 if (!r_glsl_permutation->compiled)
1407 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1408 R_GLSL_CompilePermutation(perm, mode, permutation);
1410 if (!r_glsl_permutation->program)
1412 // remove features until we find a valid permutation
1414 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1416 // reduce i more quickly whenever it would not remove any bits
1417 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1418 if (!(permutation & j))
1421 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1422 if (!r_glsl_permutation->compiled)
1423 R_GLSL_CompilePermutation(perm, mode, permutation);
1424 if (r_glsl_permutation->program)
1427 if (i >= SHADERPERMUTATION_COUNT)
1429 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1430 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1431 qglUseProgram(0);CHECKGLERROR
1432 return; // no bit left to clear, entire mode is broken
1437 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1439 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1440 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1441 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1449 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1450 extern D3DCAPS9 vid_d3d9caps;
1453 struct r_hlsl_permutation_s;
1454 typedef struct r_hlsl_permutation_s
1456 /// hash lookup data
1457 struct r_hlsl_permutation_s *hashnext;
1459 dpuint64 permutation;
1461 /// indicates if we have tried compiling this permutation already
1463 /// NULL if compilation failed
1464 IDirect3DVertexShader9 *vertexshader;
1465 IDirect3DPixelShader9 *pixelshader;
1467 r_hlsl_permutation_t;
1469 typedef enum D3DVSREGISTER_e
1471 D3DVSREGISTER_TexMatrix = 0, // float4x4
1472 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1473 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1474 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1475 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1476 D3DVSREGISTER_ModelToLight = 20, // float4x4
1477 D3DVSREGISTER_EyePosition = 24,
1478 D3DVSREGISTER_FogPlane = 25,
1479 D3DVSREGISTER_LightDir = 26,
1480 D3DVSREGISTER_LightPosition = 27,
1484 typedef enum D3DPSREGISTER_e
1486 D3DPSREGISTER_Alpha = 0,
1487 D3DPSREGISTER_BloomBlur_Parameters = 1,
1488 D3DPSREGISTER_ClientTime = 2,
1489 D3DPSREGISTER_Color_Ambient = 3,
1490 D3DPSREGISTER_Color_Diffuse = 4,
1491 D3DPSREGISTER_Color_Specular = 5,
1492 D3DPSREGISTER_Color_Glow = 6,
1493 D3DPSREGISTER_Color_Pants = 7,
1494 D3DPSREGISTER_Color_Shirt = 8,
1495 D3DPSREGISTER_DeferredColor_Ambient = 9,
1496 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1497 D3DPSREGISTER_DeferredColor_Specular = 11,
1498 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1499 D3DPSREGISTER_DeferredMod_Specular = 13,
1500 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1501 D3DPSREGISTER_EyePosition = 15, // unused
1502 D3DPSREGISTER_FogColor = 16,
1503 D3DPSREGISTER_FogHeightFade = 17,
1504 D3DPSREGISTER_FogPlane = 18,
1505 D3DPSREGISTER_FogPlaneViewDist = 19,
1506 D3DPSREGISTER_FogRangeRecip = 20,
1507 D3DPSREGISTER_LightColor = 21,
1508 D3DPSREGISTER_LightDir = 22, // unused
1509 D3DPSREGISTER_LightPosition = 23,
1510 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1511 D3DPSREGISTER_PixelSize = 25,
1512 D3DPSREGISTER_ReflectColor = 26,
1513 D3DPSREGISTER_ReflectFactor = 27,
1514 D3DPSREGISTER_ReflectOffset = 28,
1515 D3DPSREGISTER_RefractColor = 29,
1516 D3DPSREGISTER_Saturation = 30,
1517 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1518 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1519 D3DPSREGISTER_ScreenToDepth = 33,
1520 D3DPSREGISTER_ShadowMap_Parameters = 34,
1521 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1522 D3DPSREGISTER_SpecularPower = 36,
1523 D3DPSREGISTER_UserVec1 = 37,
1524 D3DPSREGISTER_UserVec2 = 38,
1525 D3DPSREGISTER_UserVec3 = 39,
1526 D3DPSREGISTER_UserVec4 = 40,
1527 D3DPSREGISTER_ViewTintColor = 41,
1528 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1529 D3DPSREGISTER_BloomColorSubtract = 43,
1530 D3DPSREGISTER_ViewToLight = 44, // float4x4
1531 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1532 D3DPSREGISTER_NormalmapScrollBlend = 52,
1533 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1534 D3DPSREGISTER_OffsetMapping_Bias = 54,
1539 /// information about each possible shader permutation
1540 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1541 /// currently selected permutation
1542 r_hlsl_permutation_t *r_hlsl_permutation;
1543 /// storage for permutations linked in the hash table
1544 memexpandablearray_t r_hlsl_permutationarray;
1546 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1548 //unsigned int hashdepth = 0;
1549 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1550 r_hlsl_permutation_t *p;
1551 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1553 if (p->mode == mode && p->permutation == permutation)
1555 //if (hashdepth > 10)
1556 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1561 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1563 p->permutation = permutation;
1564 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1565 r_hlsl_permutationhash[mode][hashindex] = p;
1566 //if (hashdepth > 10)
1567 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1572 //#include <d3dx9shader.h>
1573 //#include <d3dx9mesh.h>
1575 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1577 DWORD *vsbin = NULL;
1578 DWORD *psbin = NULL;
1579 fs_offset_t vsbinsize;
1580 fs_offset_t psbinsize;
1581 // IDirect3DVertexShader9 *vs = NULL;
1582 // IDirect3DPixelShader9 *ps = NULL;
1583 ID3DXBuffer *vslog = NULL;
1584 ID3DXBuffer *vsbuffer = NULL;
1585 ID3DXConstantTable *vsconstanttable = NULL;
1586 ID3DXBuffer *pslog = NULL;
1587 ID3DXBuffer *psbuffer = NULL;
1588 ID3DXConstantTable *psconstanttable = NULL;
1591 char temp[MAX_INPUTLINE];
1592 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1594 qboolean debugshader = gl_paranoid.integer != 0;
1595 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1596 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1599 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1600 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1602 if ((!vsbin && vertstring) || (!psbin && fragstring))
1604 const char* dllnames_d3dx9 [] =
1628 dllhandle_t d3dx9_dll = NULL;
1629 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1630 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1631 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1632 dllfunction_t d3dx9_dllfuncs[] =
1634 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1635 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1636 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1639 // 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...
1640 #ifndef ID3DXBuffer_GetBufferPointer
1641 #if !defined(__cplusplus) || defined(CINTERFACE)
1642 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1643 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1644 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1646 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1647 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1648 #define ID3DXBuffer_Release(p) (p)->Release()
1651 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1653 DWORD shaderflags = 0;
1655 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1656 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1657 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1658 if (vertstring && vertstring[0])
1662 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1663 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1666 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1669 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1670 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1671 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1672 ID3DXBuffer_Release(vsbuffer);
1676 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1677 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1678 ID3DXBuffer_Release(vslog);
1681 if (fragstring && fragstring[0])
1685 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1686 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1689 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1692 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1693 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1694 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1695 ID3DXBuffer_Release(psbuffer);
1699 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1700 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1701 ID3DXBuffer_Release(pslog);
1704 Sys_UnloadLibrary(&d3dx9_dll);
1707 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1711 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1712 if (FAILED(vsresult))
1713 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1714 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1715 if (FAILED(psresult))
1716 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1718 // free the shader data
1719 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1720 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1723 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1726 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1727 int vertstring_length = 0;
1728 int geomstring_length = 0;
1729 int fragstring_length = 0;
1732 char *vertstring, *geomstring, *fragstring;
1733 char permutationname[256];
1734 char cachename[256];
1735 int vertstrings_count = 0;
1736 int geomstrings_count = 0;
1737 int fragstrings_count = 0;
1738 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1745 p->vertexshader = NULL;
1746 p->pixelshader = NULL;
1748 permutationname[0] = 0;
1750 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1752 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1753 strlcat(cachename, "hlsl/", sizeof(cachename));
1755 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1756 vertstrings_count = 0;
1757 geomstrings_count = 0;
1758 fragstrings_count = 0;
1759 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1760 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1761 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1763 // the first pretext is which type of shader to compile as
1764 // (later these will all be bound together as a program object)
1765 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1766 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1767 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1769 // the second pretext is the mode (for example a light source)
1770 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1771 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1772 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1773 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1774 strlcat(cachename, modeinfo->name, sizeof(cachename));
1776 // now add all the permutation pretexts
1777 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1779 if (permutation & (1ll<<i))
1781 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1782 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1783 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1784 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1785 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1789 // keep line numbers correct
1790 vertstrings_list[vertstrings_count++] = "\n";
1791 geomstrings_list[geomstrings_count++] = "\n";
1792 fragstrings_list[fragstrings_count++] = "\n";
1797 R_CompileShader_AddStaticParms(mode, permutation);
1798 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1799 vertstrings_count += shaderstaticparms_count;
1800 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1801 geomstrings_count += shaderstaticparms_count;
1802 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1803 fragstrings_count += shaderstaticparms_count;
1805 // replace spaces in the cachename with _ characters
1806 for (i = 0;cachename[i];i++)
1807 if (cachename[i] == ' ')
1810 // now append the shader text itself
1811 vertstrings_list[vertstrings_count++] = sourcestring;
1812 geomstrings_list[geomstrings_count++] = sourcestring;
1813 fragstrings_list[fragstrings_count++] = sourcestring;
1815 vertstring_length = 0;
1816 for (i = 0;i < vertstrings_count;i++)
1817 vertstring_length += (int)strlen(vertstrings_list[i]);
1818 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1819 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1820 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1822 geomstring_length = 0;
1823 for (i = 0;i < geomstrings_count;i++)
1824 geomstring_length += (int)strlen(geomstrings_list[i]);
1825 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1826 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1827 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1829 fragstring_length = 0;
1830 for (i = 0;i < fragstrings_count;i++)
1831 fragstring_length += (int)strlen(fragstrings_list[i]);
1832 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1833 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1834 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1836 // try to load the cached shader, or generate one
1837 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1839 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1840 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1842 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1846 Mem_Free(vertstring);
1848 Mem_Free(geomstring);
1850 Mem_Free(fragstring);
1852 Mem_Free(sourcestring);
1855 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1856 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1857 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);}
1858 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);}
1859 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);}
1860 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);}
1862 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1863 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1864 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);}
1865 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);}
1866 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);}
1867 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);}
1869 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1871 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1872 if (r_hlsl_permutation != perm)
1874 r_hlsl_permutation = perm;
1875 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1877 if (!r_hlsl_permutation->compiled)
1878 R_HLSL_CompilePermutation(perm, mode, permutation);
1879 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1881 // remove features until we find a valid permutation
1883 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1885 // reduce i more quickly whenever it would not remove any bits
1886 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1887 if (!(permutation & j))
1890 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1891 if (!r_hlsl_permutation->compiled)
1892 R_HLSL_CompilePermutation(perm, mode, permutation);
1893 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1896 if (i >= SHADERPERMUTATION_COUNT)
1898 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1899 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1900 return; // no bit left to clear, entire mode is broken
1904 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1905 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1907 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1908 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1909 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1913 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1915 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1916 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1917 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1918 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1921 void R_GLSL_Restart_f(void)
1923 unsigned int i, limit;
1924 switch(vid.renderpath)
1926 case RENDERPATH_D3D9:
1929 r_hlsl_permutation_t *p;
1930 r_hlsl_permutation = NULL;
1931 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1932 for (i = 0;i < limit;i++)
1934 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1936 if (p->vertexshader)
1937 IDirect3DVertexShader9_Release(p->vertexshader);
1939 IDirect3DPixelShader9_Release(p->pixelshader);
1940 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1943 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1947 case RENDERPATH_D3D10:
1948 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1950 case RENDERPATH_D3D11:
1951 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1953 case RENDERPATH_GL20:
1954 case RENDERPATH_GLES2:
1956 r_glsl_permutation_t *p;
1957 r_glsl_permutation = NULL;
1958 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1959 for (i = 0;i < limit;i++)
1961 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1963 GL_Backend_FreeProgram(p->program);
1964 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1967 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1970 case RENDERPATH_GL11:
1971 case RENDERPATH_GL13:
1972 case RENDERPATH_GLES1:
1974 case RENDERPATH_SOFT:
1979 static void R_GLSL_DumpShader_f(void)
1981 int i, language, mode, dupe;
1983 shadermodeinfo_t *modeinfo;
1986 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1988 modeinfo = shadermodeinfo[language];
1989 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1991 // don't dump the same file multiple times (most or all shaders come from the same file)
1992 for (dupe = mode - 1;dupe >= 0;dupe--)
1993 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1997 text = modeinfo[mode].builtinstring;
2000 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2003 FS_Print(file, "/* The engine may define the following macros:\n");
2004 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2005 for (i = 0;i < SHADERMODE_COUNT;i++)
2006 FS_Print(file, modeinfo[i].pretext);
2007 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2008 FS_Print(file, shaderpermutationinfo[i].pretext);
2009 FS_Print(file, "*/\n");
2010 FS_Print(file, text);
2012 Con_Printf("%s written\n", modeinfo[mode].filename);
2015 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2020 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2022 dpuint64 permutation = 0;
2023 if (r_trippy.integer && !notrippy)
2024 permutation |= SHADERPERMUTATION_TRIPPY;
2025 permutation |= SHADERPERMUTATION_VIEWTINT;
2027 permutation |= SHADERPERMUTATION_DIFFUSE;
2029 permutation |= SHADERPERMUTATION_SPECULAR;
2030 if (texturemode == GL_MODULATE)
2031 permutation |= SHADERPERMUTATION_COLORMAPPING;
2032 else if (texturemode == GL_ADD)
2033 permutation |= SHADERPERMUTATION_GLOW;
2034 else if (texturemode == GL_DECAL)
2035 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2036 if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2037 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2038 if (suppresstexalpha)
2039 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2041 texturemode = GL_MODULATE;
2042 if (vid.allowalphatocoverage)
2043 GL_AlphaToCoverage(false);
2044 switch (vid.renderpath)
2046 case RENDERPATH_D3D9:
2048 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2049 R_Mesh_TexBind(GL20TU_FIRST , first );
2050 R_Mesh_TexBind(GL20TU_SECOND, second);
2051 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2052 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2055 case RENDERPATH_D3D10:
2056 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2058 case RENDERPATH_D3D11:
2059 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2061 case RENDERPATH_GL20:
2062 case RENDERPATH_GLES2:
2063 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2064 if (r_glsl_permutation->tex_Texture_First >= 0)
2065 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2066 if (r_glsl_permutation->tex_Texture_Second >= 0)
2067 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2068 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2069 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2071 case RENDERPATH_GL13:
2072 case RENDERPATH_GLES1:
2073 R_Mesh_TexBind(0, first );
2074 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2075 R_Mesh_TexMatrix(0, NULL);
2076 R_Mesh_TexBind(1, second);
2079 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2080 R_Mesh_TexMatrix(1, NULL);
2083 case RENDERPATH_GL11:
2084 R_Mesh_TexBind(0, first );
2085 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2086 R_Mesh_TexMatrix(0, NULL);
2088 case RENDERPATH_SOFT:
2089 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2090 R_Mesh_TexBind(GL20TU_FIRST , first );
2091 R_Mesh_TexBind(GL20TU_SECOND, second);
2096 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2098 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2101 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2103 dpuint64 permutation = 0;
2104 if (r_trippy.integer && !notrippy)
2105 permutation |= SHADERPERMUTATION_TRIPPY;
2107 permutation |= SHADERPERMUTATION_DEPTHRGB;
2109 permutation |= SHADERPERMUTATION_SKELETAL;
2111 if (vid.allowalphatocoverage)
2112 GL_AlphaToCoverage(false);
2113 switch (vid.renderpath)
2115 case RENDERPATH_D3D9:
2117 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2120 case RENDERPATH_D3D10:
2121 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2123 case RENDERPATH_D3D11:
2124 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2126 case RENDERPATH_GL20:
2127 case RENDERPATH_GLES2:
2128 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2130 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);
2133 case RENDERPATH_GL13:
2134 case RENDERPATH_GLES1:
2135 R_Mesh_TexBind(0, 0);
2136 R_Mesh_TexBind(1, 0);
2138 case RENDERPATH_GL11:
2139 R_Mesh_TexBind(0, 0);
2141 case RENDERPATH_SOFT:
2142 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2147 extern qboolean r_shadow_usingdeferredprepass;
2148 extern rtexture_t *r_shadow_attenuationgradienttexture;
2149 extern rtexture_t *r_shadow_attenuation2dtexture;
2150 extern rtexture_t *r_shadow_attenuation3dtexture;
2151 extern qboolean r_shadow_usingshadowmap2d;
2152 extern qboolean r_shadow_usingshadowmaportho;
2153 extern float r_shadow_modelshadowmap_texturescale[4];
2154 extern float r_shadow_modelshadowmap_parameters[4];
2155 extern float r_shadow_lightshadowmap_texturescale[4];
2156 extern float r_shadow_lightshadowmap_parameters[4];
2157 extern qboolean r_shadow_shadowmapvsdct;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2160 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2161 extern matrix4x4_t r_shadow_shadowmapmatrix;
2162 extern int r_shadow_prepass_width;
2163 extern int r_shadow_prepass_height;
2164 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2165 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2166 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2167 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2169 #define BLENDFUNC_ALLOWS_COLORMOD 1
2170 #define BLENDFUNC_ALLOWS_FOG 2
2171 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2172 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2173 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2174 static int R_BlendFuncFlags(int src, int dst)
2178 // a blendfunc allows colormod if:
2179 // a) it can never keep the destination pixel invariant, or
2180 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2181 // this is to prevent unintended side effects from colormod
2183 // a blendfunc allows fog if:
2184 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2185 // this is to prevent unintended side effects from fog
2187 // these checks are the output of fogeval.pl
2189 r |= BLENDFUNC_ALLOWS_COLORMOD;
2190 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2191 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2192 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2193 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2194 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2198 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2199 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2200 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2201 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2202 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2203 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2204 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2205 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2208 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2209 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2210 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2215 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2217 // select a permutation of the lighting shader appropriate to this
2218 // combination of texture, entity, light source, and fogging, only use the
2219 // minimum features necessary to avoid wasting rendering time in the
2220 // fragment shader on features that are not being used
2221 dpuint64 permutation = 0;
2222 unsigned int mode = 0;
2224 static float dummy_colormod[3] = {1, 1, 1};
2225 float *colormod = rsurface.colormod;
2227 matrix4x4_t tempmatrix;
2228 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2229 if (r_trippy.integer && !notrippy)
2230 permutation |= SHADERPERMUTATION_TRIPPY;
2231 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2232 permutation |= SHADERPERMUTATION_ALPHAKILL;
2233 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2234 permutation |= SHADERPERMUTATION_OCCLUDE;
2235 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2236 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2237 if (rsurfacepass == RSURFPASS_BACKGROUND)
2239 // distorted background
2240 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2242 mode = SHADERMODE_WATER;
2243 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2244 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2245 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2247 // this is the right thing to do for wateralpha
2248 GL_BlendFunc(GL_ONE, GL_ZERO);
2249 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2253 // this is the right thing to do for entity alpha
2254 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2258 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2260 mode = SHADERMODE_REFRACTION;
2261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2268 mode = SHADERMODE_GENERIC;
2269 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2270 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2273 if (vid.allowalphatocoverage)
2274 GL_AlphaToCoverage(false);
2276 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2278 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2280 switch(rsurface.texture->offsetmapping)
2282 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2283 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285 case OFFSETMAPPING_OFF: break;
2288 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290 // normalmap (deferred prepass), may use alpha test on diffuse
2291 mode = SHADERMODE_DEFERREDGEOMETRY;
2292 GL_BlendFunc(GL_ONE, GL_ZERO);
2293 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2294 if (vid.allowalphatocoverage)
2295 GL_AlphaToCoverage(false);
2297 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2299 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2301 switch(rsurface.texture->offsetmapping)
2303 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2304 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306 case OFFSETMAPPING_OFF: break;
2309 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2310 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2311 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2312 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2314 mode = SHADERMODE_LIGHTSOURCE;
2315 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2316 permutation |= SHADERPERMUTATION_CUBEFILTER;
2317 if (diffusescale > 0)
2318 permutation |= SHADERPERMUTATION_DIFFUSE;
2319 if (specularscale > 0)
2320 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2321 if (r_refdef.fogenabled)
2322 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323 if (rsurface.texture->colormapping)
2324 permutation |= SHADERPERMUTATION_COLORMAPPING;
2325 if (r_shadow_usingshadowmap2d)
2327 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328 if(r_shadow_shadowmapvsdct)
2329 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2331 if (r_shadow_shadowmap2ddepthbuffer)
2332 permutation |= SHADERPERMUTATION_DEPTHRGB;
2334 if (rsurface.texture->reflectmasktexture)
2335 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2337 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2338 if (vid.allowalphatocoverage)
2339 GL_AlphaToCoverage(false);
2341 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2343 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2345 switch(rsurface.texture->offsetmapping)
2347 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350 case OFFSETMAPPING_OFF: break;
2353 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2356 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2357 // unshaded geometry (fullbright or ambient model lighting)
2358 mode = SHADERMODE_FLATCOLOR;
2359 ambientscale = diffusescale = specularscale = 0;
2360 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2361 permutation |= SHADERPERMUTATION_GLOW;
2362 if (r_refdef.fogenabled)
2363 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2364 if (rsurface.texture->colormapping)
2365 permutation |= SHADERPERMUTATION_COLORMAPPING;
2366 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2369 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371 if (r_shadow_shadowmap2ddepthbuffer)
2372 permutation |= SHADERPERMUTATION_DEPTHRGB;
2374 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375 permutation |= SHADERPERMUTATION_REFLECTION;
2376 if (rsurface.texture->reflectmasktexture)
2377 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2378 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2379 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2380 // when using alphatocoverage, we don't need alphakill
2381 if (vid.allowalphatocoverage)
2383 if (r_transparent_alphatocoverage.integer)
2385 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2386 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2389 GL_AlphaToCoverage(false);
2392 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2394 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2396 switch(rsurface.texture->offsetmapping)
2398 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2399 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2400 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2401 case OFFSETMAPPING_OFF: break;
2404 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2405 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2406 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2407 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2408 // directional model lighting
2409 mode = SHADERMODE_LIGHTDIRECTION;
2410 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2411 permutation |= SHADERPERMUTATION_GLOW;
2412 permutation |= SHADERPERMUTATION_DIFFUSE;
2413 if (specularscale > 0)
2414 permutation |= SHADERPERMUTATION_SPECULAR;
2415 if (r_refdef.fogenabled)
2416 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2417 if (rsurface.texture->colormapping)
2418 permutation |= SHADERPERMUTATION_COLORMAPPING;
2419 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2421 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2422 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2424 if (r_shadow_shadowmap2ddepthbuffer)
2425 permutation |= SHADERPERMUTATION_DEPTHRGB;
2427 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2428 permutation |= SHADERPERMUTATION_REFLECTION;
2429 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2430 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2431 if (rsurface.texture->reflectmasktexture)
2432 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2433 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2435 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2436 if (r_shadow_bouncegrid_state.directional)
2437 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2439 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2440 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2441 // when using alphatocoverage, we don't need alphakill
2442 if (vid.allowalphatocoverage)
2444 if (r_transparent_alphatocoverage.integer)
2446 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2447 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2450 GL_AlphaToCoverage(false);
2453 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2455 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2457 switch(rsurface.texture->offsetmapping)
2459 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2460 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2461 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2462 case OFFSETMAPPING_OFF: break;
2465 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2466 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2467 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2468 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2469 // ambient model lighting
2470 mode = SHADERMODE_LIGHTDIRECTION;
2471 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2472 permutation |= SHADERPERMUTATION_GLOW;
2473 if (r_refdef.fogenabled)
2474 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2475 if (rsurface.texture->colormapping)
2476 permutation |= SHADERPERMUTATION_COLORMAPPING;
2477 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2479 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2480 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2482 if (r_shadow_shadowmap2ddepthbuffer)
2483 permutation |= SHADERPERMUTATION_DEPTHRGB;
2485 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2486 permutation |= SHADERPERMUTATION_REFLECTION;
2487 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2488 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2489 if (rsurface.texture->reflectmasktexture)
2490 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2491 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2493 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2494 if (r_shadow_bouncegrid_state.directional)
2495 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2497 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2498 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2499 // when using alphatocoverage, we don't need alphakill
2500 if (vid.allowalphatocoverage)
2502 if (r_transparent_alphatocoverage.integer)
2504 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2505 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2508 GL_AlphaToCoverage(false);
2513 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2515 switch(rsurface.texture->offsetmapping)
2517 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2518 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2519 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2520 case OFFSETMAPPING_OFF: break;
2523 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2524 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2525 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2526 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2528 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2529 permutation |= SHADERPERMUTATION_GLOW;
2530 if (r_refdef.fogenabled)
2531 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2532 if (rsurface.texture->colormapping)
2533 permutation |= SHADERPERMUTATION_COLORMAPPING;
2534 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2536 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2537 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2539 if (r_shadow_shadowmap2ddepthbuffer)
2540 permutation |= SHADERPERMUTATION_DEPTHRGB;
2542 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2543 permutation |= SHADERPERMUTATION_REFLECTION;
2544 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2545 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2546 if (rsurface.texture->reflectmasktexture)
2547 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2548 if (FAKELIGHT_ENABLED)
2550 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2551 mode = SHADERMODE_FAKELIGHT;
2552 permutation |= SHADERPERMUTATION_DIFFUSE;
2553 if (specularscale > 0)
2554 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2556 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2558 // deluxemapping (light direction texture)
2559 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2560 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2562 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2563 permutation |= SHADERPERMUTATION_DIFFUSE;
2564 if (specularscale > 0)
2565 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2567 else if (r_glsl_deluxemapping.integer >= 2)
2569 // fake deluxemapping (uniform light direction in tangentspace)
2570 if (rsurface.uselightmaptexture)
2571 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2573 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2574 permutation |= SHADERPERMUTATION_DIFFUSE;
2575 if (specularscale > 0)
2576 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2578 else if (rsurface.uselightmaptexture)
2580 // ordinary lightmapping (q1bsp, q3bsp)
2581 mode = SHADERMODE_LIGHTMAP;
2585 // ordinary vertex coloring (q3bsp)
2586 mode = SHADERMODE_VERTEXCOLOR;
2588 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2590 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2591 if (r_shadow_bouncegrid_state.directional)
2592 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2594 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2595 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2596 // when using alphatocoverage, we don't need alphakill
2597 if (vid.allowalphatocoverage)
2599 if (r_transparent_alphatocoverage.integer)
2601 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2602 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2605 GL_AlphaToCoverage(false);
2608 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2609 colormod = dummy_colormod;
2610 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2611 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2612 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2613 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2614 switch(vid.renderpath)
2616 case RENDERPATH_D3D9:
2618 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);
2619 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2620 R_SetupShader_SetPermutationHLSL(mode, permutation);
2621 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2622 if (mode == SHADERMODE_LIGHTSOURCE)
2624 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2625 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2629 if (mode == SHADERMODE_LIGHTDIRECTION)
2631 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2634 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2635 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2636 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2637 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2638 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2640 if (mode == SHADERMODE_LIGHTSOURCE)
2642 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2643 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2644 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2645 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2646 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2648 // additive passes are only darkened by fog, not tinted
2649 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2650 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2654 if (mode == SHADERMODE_FLATCOLOR)
2656 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2658 else if (mode == SHADERMODE_LIGHTDIRECTION)
2660 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2661 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2662 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2663 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2664 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2665 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2666 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2670 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2671 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2672 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2673 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2674 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2676 // additive passes are only darkened by fog, not tinted
2677 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2678 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2680 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2681 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2682 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2683 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2684 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2685 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2686 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2687 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2688 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2689 if (mode == SHADERMODE_WATER)
2690 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2692 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2694 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2695 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2699 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2700 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2702 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2703 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2704 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2705 if (rsurface.texture->pantstexture)
2706 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2708 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2709 if (rsurface.texture->shirttexture)
2710 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2712 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2713 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2714 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2715 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2716 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2717 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2718 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2719 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2720 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2721 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2723 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2724 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2725 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2726 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2728 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2729 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2730 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2731 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2732 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2733 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2734 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2735 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2736 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2737 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2738 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2739 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2740 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2741 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2742 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2743 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2744 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2745 if (rsurfacepass == RSURFPASS_BACKGROUND)
2747 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2748 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2749 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2753 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2755 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2756 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2757 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2758 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2760 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2761 if (rsurface.rtlight)
2763 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2764 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2769 case RENDERPATH_D3D10:
2770 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2772 case RENDERPATH_D3D11:
2773 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2775 case RENDERPATH_GL20:
2776 case RENDERPATH_GLES2:
2777 if (!vid.useinterleavedarrays)
2779 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);
2780 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2781 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2782 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2783 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2784 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2785 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2786 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2787 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2788 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2789 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2793 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);
2794 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2796 // this has to be after RSurf_PrepareVerticesForBatch
2797 if (rsurface.batchskeletaltransform3x4buffer)
2798 permutation |= SHADERPERMUTATION_SKELETAL;
2799 R_SetupShader_SetPermutationGLSL(mode, permutation);
2800 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2801 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);
2803 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2804 if (mode == SHADERMODE_LIGHTSOURCE)
2806 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2807 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2808 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2809 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2810 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2811 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2813 // additive passes are only darkened by fog, not tinted
2814 if (r_glsl_permutation->loc_FogColor >= 0)
2815 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2816 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2820 if (mode == SHADERMODE_FLATCOLOR)
2822 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2824 else if (mode == SHADERMODE_LIGHTDIRECTION)
2826 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2827 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2828 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2829 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2830 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2831 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2832 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2836 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2837 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2838 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2839 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2840 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2842 // additive passes are only darkened by fog, not tinted
2843 if (r_glsl_permutation->loc_FogColor >= 0)
2845 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2846 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2848 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2850 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2851 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]);
2852 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]);
2853 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2854 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2855 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2856 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2857 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2858 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2860 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2861 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2862 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2863 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2865 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]);
2866 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]);
2870 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]);
2871 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]);
2874 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2875 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2876 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2877 if (r_glsl_permutation->loc_Color_Pants >= 0)
2879 if (rsurface.texture->pantstexture)
2880 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2882 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2884 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2886 if (rsurface.texture->shirttexture)
2887 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2889 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2891 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]);
2892 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2893 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2894 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2895 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2896 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2897 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2898 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2899 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2901 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);
2902 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2903 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]);
2904 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2905 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);}
2906 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2908 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2909 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2910 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2911 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2912 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2913 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2914 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2915 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2916 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2917 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2918 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2919 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2920 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2921 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2922 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2923 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2924 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2925 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2926 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2927 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2928 if (rsurfacepass == RSURFPASS_BACKGROUND)
2930 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2931 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2932 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2936 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2938 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2939 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2940 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2941 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2943 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2944 if (rsurface.rtlight)
2946 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2947 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2950 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2953 case RENDERPATH_GL11:
2954 case RENDERPATH_GL13:
2955 case RENDERPATH_GLES1:
2957 case RENDERPATH_SOFT:
2958 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);
2959 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2960 R_SetupShader_SetPermutationSoft(mode, permutation);
2961 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2962 if (mode == SHADERMODE_LIGHTSOURCE)
2964 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2965 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2966 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2967 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2968 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2969 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2971 // additive passes are only darkened by fog, not tinted
2972 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2973 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2977 if (mode == SHADERMODE_FLATCOLOR)
2979 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2981 else if (mode == SHADERMODE_LIGHTDIRECTION)
2983 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2984 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2986 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2987 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2988 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2989 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2993 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2994 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2995 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2996 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2997 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2999 // additive passes are only darkened by fog, not tinted
3000 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
3001 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
3003 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3004 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
3005 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]);
3006 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]);
3007 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3008 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3009 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3010 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3011 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3012 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3014 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3015 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3016 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3017 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3019 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]);
3020 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]);
3024 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]);
3025 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]);
3028 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3029 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
3030 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3031 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3033 if (rsurface.texture->pantstexture)
3034 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3036 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3038 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3040 if (rsurface.texture->shirttexture)
3041 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3043 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3045 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3046 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3047 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3048 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3049 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3050 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3051 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3052 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3053 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3055 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3056 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3057 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3058 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3060 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3061 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3062 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3063 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3064 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3065 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3066 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3067 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3068 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3069 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3070 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3071 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3072 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3073 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3074 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3075 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3076 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3077 if (rsurfacepass == RSURFPASS_BACKGROUND)
3079 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3080 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3081 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3085 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3087 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3088 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3089 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3090 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3092 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3093 if (rsurface.rtlight)
3095 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3096 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3103 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3105 // select a permutation of the lighting shader appropriate to this
3106 // combination of texture, entity, light source, and fogging, only use the
3107 // minimum features necessary to avoid wasting rendering time in the
3108 // fragment shader on features that are not being used
3109 dpuint64 permutation = 0;
3110 unsigned int mode = 0;
3111 const float *lightcolorbase = rtlight->currentcolor;
3112 float ambientscale = rtlight->ambientscale;
3113 float diffusescale = rtlight->diffusescale;
3114 float specularscale = rtlight->specularscale;
3115 // this is the location of the light in view space
3116 vec3_t viewlightorigin;
3117 // this transforms from view space (camera) to light space (cubemap)
3118 matrix4x4_t viewtolight;
3119 matrix4x4_t lighttoview;
3120 float viewtolight16f[16];
3122 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3123 if (rtlight->currentcubemap != r_texture_whitecube)
3124 permutation |= SHADERPERMUTATION_CUBEFILTER;
3125 if (diffusescale > 0)
3126 permutation |= SHADERPERMUTATION_DIFFUSE;
3127 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3128 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3129 if (r_shadow_usingshadowmap2d)
3131 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3132 if (r_shadow_shadowmapvsdct)
3133 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3135 if (r_shadow_shadowmap2ddepthbuffer)
3136 permutation |= SHADERPERMUTATION_DEPTHRGB;
3138 if (vid.allowalphatocoverage)
3139 GL_AlphaToCoverage(false);
3140 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3141 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3142 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3143 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3144 switch(vid.renderpath)
3146 case RENDERPATH_D3D9:
3148 R_SetupShader_SetPermutationHLSL(mode, permutation);
3149 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3150 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3151 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3152 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3153 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3154 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3155 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3156 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);
3157 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3158 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3160 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3161 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3162 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3163 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3164 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3167 case RENDERPATH_D3D10:
3168 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3170 case RENDERPATH_D3D11:
3171 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3173 case RENDERPATH_GL20:
3174 case RENDERPATH_GLES2:
3175 R_SetupShader_SetPermutationGLSL(mode, permutation);
3176 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3177 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3178 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3179 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3180 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3181 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]);
3182 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]);
3183 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);
3184 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]);
3185 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3187 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3188 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3189 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3190 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3191 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3193 case RENDERPATH_GL11:
3194 case RENDERPATH_GL13:
3195 case RENDERPATH_GLES1:
3197 case RENDERPATH_SOFT:
3198 R_SetupShader_SetPermutationGLSL(mode, permutation);
3199 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3200 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3201 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3202 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3203 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3204 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]);
3205 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]);
3206 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);
3207 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3208 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3210 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3211 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3212 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3213 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3214 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3219 #define SKINFRAME_HASH 1024
3223 unsigned int loadsequence; // incremented each level change
3224 memexpandablearray_t array;
3225 skinframe_t *hash[SKINFRAME_HASH];
3228 r_skinframe_t r_skinframe;
3230 void R_SkinFrame_PrepareForPurge(void)
3232 r_skinframe.loadsequence++;
3233 // wrap it without hitting zero
3234 if (r_skinframe.loadsequence >= 200)
3235 r_skinframe.loadsequence = 1;
3238 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3242 // mark the skinframe as used for the purging code
3243 skinframe->loadsequence = r_skinframe.loadsequence;
3246 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3248 if (s->merged == s->base)
3250 R_PurgeTexture(s->stain); s->stain = NULL;
3251 R_PurgeTexture(s->merged); s->merged = NULL;
3252 R_PurgeTexture(s->base); s->base = NULL;
3253 R_PurgeTexture(s->pants); s->pants = NULL;
3254 R_PurgeTexture(s->shirt); s->shirt = NULL;
3255 R_PurgeTexture(s->nmap); s->nmap = NULL;
3256 R_PurgeTexture(s->gloss); s->gloss = NULL;
3257 R_PurgeTexture(s->glow); s->glow = NULL;
3258 R_PurgeTexture(s->fog); s->fog = NULL;
3259 R_PurgeTexture(s->reflect); s->reflect = NULL;
3260 s->loadsequence = 0;
3263 void R_SkinFrame_Purge(void)
3267 for (i = 0;i < SKINFRAME_HASH;i++)
3269 for (s = r_skinframe.hash[i];s;s = s->next)
3271 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3272 R_SkinFrame_PurgeSkinFrame(s);
3277 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3279 char basename[MAX_QPATH];
3281 Image_StripImageExtension(name, basename, sizeof(basename));
3283 if( last == NULL ) {
3285 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3286 item = r_skinframe.hash[hashindex];
3291 // linearly search through the hash bucket
3292 for( ; item ; item = item->next ) {
3293 if( !strcmp( item->basename, basename ) ) {
3300 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3304 char basename[MAX_QPATH];
3306 Image_StripImageExtension(name, basename, sizeof(basename));
3308 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3309 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3310 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3314 rtexture_t *dyntexture;
3315 // check whether its a dynamic texture
3316 dyntexture = CL_GetDynTexture( basename );
3317 if (!add && !dyntexture)
3319 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3320 memset(item, 0, sizeof(*item));
3321 strlcpy(item->basename, basename, sizeof(item->basename));
3322 item->base = dyntexture; // either NULL or dyntexture handle
3323 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3324 item->comparewidth = comparewidth;
3325 item->compareheight = compareheight;
3326 item->comparecrc = comparecrc;
3327 item->next = r_skinframe.hash[hashindex];
3328 r_skinframe.hash[hashindex] = item;
3330 else if (textureflags & TEXF_FORCE_RELOAD)
3332 rtexture_t *dyntexture;
3333 // check whether its a dynamic texture
3334 dyntexture = CL_GetDynTexture( basename );
3335 if (!add && !dyntexture)
3337 R_SkinFrame_PurgeSkinFrame(item);
3339 else if( item->base == NULL )
3341 rtexture_t *dyntexture;
3342 // check whether its a dynamic texture
3343 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3344 dyntexture = CL_GetDynTexture( basename );
3345 item->base = dyntexture; // either NULL or dyntexture handle
3348 R_SkinFrame_MarkUsed(item);
3352 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3354 unsigned long long avgcolor[5], wsum; \
3362 for(pix = 0; pix < cnt; ++pix) \
3365 for(comp = 0; comp < 3; ++comp) \
3367 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3370 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3372 for(comp = 0; comp < 3; ++comp) \
3373 avgcolor[comp] += getpixel * w; \
3376 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3377 avgcolor[4] += getpixel; \
3379 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3381 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3382 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3383 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3384 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3387 extern cvar_t gl_picmip;
3388 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3391 unsigned char *pixels;
3392 unsigned char *bumppixels;
3393 unsigned char *basepixels = NULL;
3394 int basepixels_width = 0;
3395 int basepixels_height = 0;
3396 skinframe_t *skinframe;
3397 rtexture_t *ddsbase = NULL;
3398 qboolean ddshasalpha = false;
3399 float ddsavgcolor[4];
3400 char basename[MAX_QPATH];
3401 int miplevel = R_PicmipForFlags(textureflags);
3402 int savemiplevel = miplevel;
3406 if (cls.state == ca_dedicated)
3409 // return an existing skinframe if already loaded
3410 // if loading of the first image fails, don't make a new skinframe as it
3411 // would cause all future lookups of this to be missing
3412 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3413 if (skinframe && skinframe->base)
3416 Image_StripImageExtension(name, basename, sizeof(basename));
3418 // check for DDS texture file first
3419 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3421 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3422 if (basepixels == NULL)
3426 // FIXME handle miplevel
3428 if (developer_loading.integer)
3429 Con_Printf("loading skin \"%s\"\n", name);
3431 // we've got some pixels to store, so really allocate this new texture now
3433 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3434 textureflags &= ~TEXF_FORCE_RELOAD;
3435 skinframe->stain = NULL;
3436 skinframe->merged = NULL;
3437 skinframe->base = NULL;
3438 skinframe->pants = NULL;
3439 skinframe->shirt = NULL;
3440 skinframe->nmap = NULL;
3441 skinframe->gloss = NULL;
3442 skinframe->glow = NULL;
3443 skinframe->fog = NULL;
3444 skinframe->reflect = NULL;
3445 skinframe->hasalpha = false;
3446 // we could store the q2animname here too
3450 skinframe->base = ddsbase;
3451 skinframe->hasalpha = ddshasalpha;
3452 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3453 if (r_loadfog && skinframe->hasalpha)
3454 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);
3455 //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]);
3459 basepixels_width = image_width;
3460 basepixels_height = image_height;
3461 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);
3462 if (textureflags & TEXF_ALPHA)
3464 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3466 if (basepixels[j] < 255)
3468 skinframe->hasalpha = true;
3472 if (r_loadfog && skinframe->hasalpha)
3474 // has transparent pixels
3475 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3476 for (j = 0;j < image_width * image_height * 4;j += 4)
3481 pixels[j+3] = basepixels[j+3];
3483 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);
3487 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3489 //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]);
3490 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3491 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3492 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3493 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3499 mymiplevel = savemiplevel;
3500 if (r_loadnormalmap)
3501 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);
3502 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3504 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3505 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3506 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3507 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3510 // _norm is the name used by tenebrae and has been adopted as standard
3511 if (r_loadnormalmap && skinframe->nmap == NULL)
3513 mymiplevel = savemiplevel;
3514 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3516 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);
3520 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3522 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3523 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3524 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);
3526 Mem_Free(bumppixels);
3528 else if (r_shadow_bumpscale_basetexture.value > 0)
3530 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3531 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3532 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);
3536 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3537 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3541 // _luma is supported only for tenebrae compatibility
3542 // _glow is the preferred name
3543 mymiplevel = savemiplevel;
3544 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))))
3546 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);
3548 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3549 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3551 Mem_Free(pixels);pixels = NULL;
3554 mymiplevel = savemiplevel;
3555 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3557 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);
3559 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3560 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3566 mymiplevel = savemiplevel;
3567 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3569 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);
3571 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3572 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3578 mymiplevel = savemiplevel;
3579 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3581 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);
3583 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3584 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3590 mymiplevel = savemiplevel;
3591 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3593 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);
3595 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3596 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3603 Mem_Free(basepixels);
3608 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3609 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3612 skinframe_t *skinframe;
3615 if (cls.state == ca_dedicated)
3618 // if already loaded just return it, otherwise make a new skinframe
3619 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3620 if (skinframe->base)
3622 textureflags &= ~TEXF_FORCE_RELOAD;
3624 skinframe->stain = NULL;
3625 skinframe->merged = NULL;
3626 skinframe->base = NULL;
3627 skinframe->pants = NULL;
3628 skinframe->shirt = NULL;
3629 skinframe->nmap = NULL;
3630 skinframe->gloss = NULL;
3631 skinframe->glow = NULL;
3632 skinframe->fog = NULL;
3633 skinframe->reflect = NULL;
3634 skinframe->hasalpha = false;
3636 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3640 if (developer_loading.integer)
3641 Con_Printf("loading 32bit skin \"%s\"\n", name);
3643 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3645 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3646 unsigned char *b = a + width * height * 4;
3647 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3648 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);
3651 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3652 if (textureflags & TEXF_ALPHA)
3654 for (i = 3;i < width * height * 4;i += 4)
3656 if (skindata[i] < 255)
3658 skinframe->hasalpha = true;
3662 if (r_loadfog && skinframe->hasalpha)
3664 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3665 memcpy(fogpixels, skindata, width * height * 4);
3666 for (i = 0;i < width * height * 4;i += 4)
3667 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3668 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3669 Mem_Free(fogpixels);
3673 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3674 //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]);
3679 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3683 skinframe_t *skinframe;
3685 if (cls.state == ca_dedicated)
3688 // if already loaded just return it, otherwise make a new skinframe
3689 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3690 if (skinframe->base)
3692 //textureflags &= ~TEXF_FORCE_RELOAD;
3694 skinframe->stain = NULL;
3695 skinframe->merged = NULL;
3696 skinframe->base = NULL;
3697 skinframe->pants = NULL;
3698 skinframe->shirt = NULL;
3699 skinframe->nmap = NULL;
3700 skinframe->gloss = NULL;
3701 skinframe->glow = NULL;
3702 skinframe->fog = NULL;
3703 skinframe->reflect = NULL;
3704 skinframe->hasalpha = false;
3706 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3710 if (developer_loading.integer)
3711 Con_Printf("loading quake skin \"%s\"\n", name);
3713 // 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)
3714 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3715 memcpy(skinframe->qpixels, skindata, width*height);
3716 skinframe->qwidth = width;
3717 skinframe->qheight = height;
3720 for (i = 0;i < width * height;i++)
3721 featuresmask |= palette_featureflags[skindata[i]];
3723 skinframe->hasalpha = false;
3726 skinframe->hasalpha = true;
3727 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3728 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3729 skinframe->qgeneratemerged = true;
3730 skinframe->qgeneratebase = skinframe->qhascolormapping;
3731 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3733 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3734 //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]);
3739 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3743 unsigned char *skindata;
3746 if (!skinframe->qpixels)
3749 if (!skinframe->qhascolormapping)
3750 colormapped = false;
3754 if (!skinframe->qgeneratebase)
3759 if (!skinframe->qgeneratemerged)
3763 width = skinframe->qwidth;
3764 height = skinframe->qheight;
3765 skindata = skinframe->qpixels;
3767 if (skinframe->qgeneratenmap)
3769 unsigned char *a, *b;
3770 skinframe->qgeneratenmap = false;
3771 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3772 b = a + width * height * 4;
3773 // use either a custom palette or the quake palette
3774 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3775 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3776 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);
3780 if (skinframe->qgenerateglow)
3782 skinframe->qgenerateglow = false;
3783 if (skinframe->hasalpha) // fence textures
3784 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
3786 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
3791 skinframe->qgeneratebase = false;
3792 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);
3793 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);
3794 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);
3798 skinframe->qgeneratemerged = false;
3799 if (skinframe->hasalpha) // fence textures
3800 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);
3802 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);
3805 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3807 Mem_Free(skinframe->qpixels);
3808 skinframe->qpixels = NULL;
3812 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)
3815 skinframe_t *skinframe;
3818 if (cls.state == ca_dedicated)
3821 // if already loaded just return it, otherwise make a new skinframe
3822 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3823 if (skinframe->base)
3825 textureflags &= ~TEXF_FORCE_RELOAD;
3827 skinframe->stain = NULL;
3828 skinframe->merged = NULL;
3829 skinframe->base = NULL;
3830 skinframe->pants = NULL;
3831 skinframe->shirt = NULL;
3832 skinframe->nmap = NULL;
3833 skinframe->gloss = NULL;
3834 skinframe->glow = NULL;
3835 skinframe->fog = NULL;
3836 skinframe->reflect = NULL;
3837 skinframe->hasalpha = false;
3839 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3843 if (developer_loading.integer)
3844 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3846 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3847 if (textureflags & TEXF_ALPHA)
3849 for (i = 0;i < width * height;i++)
3851 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3853 skinframe->hasalpha = true;
3857 if (r_loadfog && skinframe->hasalpha)
3858 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3861 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3862 //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]);
3867 skinframe_t *R_SkinFrame_LoadMissing(void)
3869 skinframe_t *skinframe;
3871 if (cls.state == ca_dedicated)
3874 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3875 skinframe->stain = NULL;
3876 skinframe->merged = NULL;
3877 skinframe->base = NULL;
3878 skinframe->pants = NULL;
3879 skinframe->shirt = NULL;
3880 skinframe->nmap = NULL;
3881 skinframe->gloss = NULL;
3882 skinframe->glow = NULL;
3883 skinframe->fog = NULL;
3884 skinframe->reflect = NULL;
3885 skinframe->hasalpha = false;
3887 skinframe->avgcolor[0] = rand() / RAND_MAX;
3888 skinframe->avgcolor[1] = rand() / RAND_MAX;
3889 skinframe->avgcolor[2] = rand() / RAND_MAX;
3890 skinframe->avgcolor[3] = 1;
3895 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3896 typedef struct suffixinfo_s
3899 qboolean flipx, flipy, flipdiagonal;
3902 static suffixinfo_t suffix[3][6] =
3905 {"px", false, false, false},
3906 {"nx", false, false, false},
3907 {"py", false, false, false},
3908 {"ny", false, false, false},
3909 {"pz", false, false, false},
3910 {"nz", false, false, false}
3913 {"posx", false, false, false},
3914 {"negx", false, false, false},
3915 {"posy", false, false, false},
3916 {"negy", false, false, false},
3917 {"posz", false, false, false},
3918 {"negz", false, false, false}
3921 {"rt", true, false, true},
3922 {"lf", false, true, true},
3923 {"ft", true, true, false},
3924 {"bk", false, false, false},
3925 {"up", true, false, true},
3926 {"dn", true, false, true}
3930 static int componentorder[4] = {0, 1, 2, 3};
3932 static rtexture_t *R_LoadCubemap(const char *basename)
3934 int i, j, cubemapsize;
3935 unsigned char *cubemappixels, *image_buffer;
3936 rtexture_t *cubemaptexture;
3938 // must start 0 so the first loadimagepixels has no requested width/height
3940 cubemappixels = NULL;
3941 cubemaptexture = NULL;
3942 // keep trying different suffix groups (posx, px, rt) until one loads
3943 for (j = 0;j < 3 && !cubemappixels;j++)
3945 // load the 6 images in the suffix group
3946 for (i = 0;i < 6;i++)
3948 // generate an image name based on the base and and suffix
3949 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3951 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3953 // an image loaded, make sure width and height are equal
3954 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3956 // if this is the first image to load successfully, allocate the cubemap memory
3957 if (!cubemappixels && image_width >= 1)
3959 cubemapsize = image_width;
3960 // note this clears to black, so unavailable sides are black
3961 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3963 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3965 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);
3968 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3970 Mem_Free(image_buffer);
3974 // if a cubemap loaded, upload it
3977 if (developer_loading.integer)
3978 Con_Printf("loading cubemap \"%s\"\n", basename);
3980 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);
3981 Mem_Free(cubemappixels);
3985 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3986 if (developer_loading.integer)
3988 Con_Printf("(tried tried images ");
3989 for (j = 0;j < 3;j++)
3990 for (i = 0;i < 6;i++)
3991 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3992 Con_Print(" and was unable to find any of them).\n");
3995 return cubemaptexture;
3998 rtexture_t *R_GetCubemap(const char *basename)
4001 for (i = 0;i < r_texture_numcubemaps;i++)
4002 if (r_texture_cubemaps[i] != NULL)
4003 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4004 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4005 if (i >= MAX_CUBEMAPS || !r_main_mempool)
4006 return r_texture_whitecube;
4007 r_texture_numcubemaps++;
4008 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4009 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4010 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4011 return r_texture_cubemaps[i]->texture;
4014 static void R_Main_FreeViewCache(void)
4016 if (r_refdef.viewcache.entityvisible)
4017 Mem_Free(r_refdef.viewcache.entityvisible);
4018 if (r_refdef.viewcache.world_pvsbits)
4019 Mem_Free(r_refdef.viewcache.world_pvsbits);
4020 if (r_refdef.viewcache.world_leafvisible)
4021 Mem_Free(r_refdef.viewcache.world_leafvisible);
4022 if (r_refdef.viewcache.world_surfacevisible)
4023 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4024 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4027 static void R_Main_ResizeViewCache(void)
4029 int numentities = r_refdef.scene.numentities;
4030 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4031 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4032 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4033 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4034 if (r_refdef.viewcache.maxentities < numentities)
4036 r_refdef.viewcache.maxentities = numentities;
4037 if (r_refdef.viewcache.entityvisible)
4038 Mem_Free(r_refdef.viewcache.entityvisible);
4039 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4041 if (r_refdef.viewcache.world_numclusters != numclusters)
4043 r_refdef.viewcache.world_numclusters = numclusters;
4044 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4045 if (r_refdef.viewcache.world_pvsbits)
4046 Mem_Free(r_refdef.viewcache.world_pvsbits);
4047 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4049 if (r_refdef.viewcache.world_numleafs != numleafs)
4051 r_refdef.viewcache.world_numleafs = numleafs;
4052 if (r_refdef.viewcache.world_leafvisible)
4053 Mem_Free(r_refdef.viewcache.world_leafvisible);
4054 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4056 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4058 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4059 if (r_refdef.viewcache.world_surfacevisible)
4060 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4061 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4065 extern rtexture_t *loadingscreentexture;
4066 static void gl_main_start(void)
4068 loadingscreentexture = NULL;
4069 r_texture_blanknormalmap = NULL;
4070 r_texture_white = NULL;
4071 r_texture_grey128 = NULL;
4072 r_texture_black = NULL;
4073 r_texture_whitecube = NULL;
4074 r_texture_normalizationcube = NULL;
4075 r_texture_fogattenuation = NULL;
4076 r_texture_fogheighttexture = NULL;
4077 r_texture_gammaramps = NULL;
4078 r_texture_numcubemaps = 0;
4079 r_uniformbufferalignment = 32;
4081 r_loaddds = r_texture_dds_load.integer != 0;
4082 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4084 switch(vid.renderpath)
4086 case RENDERPATH_GL20:
4087 case RENDERPATH_D3D9:
4088 case RENDERPATH_D3D10:
4089 case RENDERPATH_D3D11:
4090 case RENDERPATH_SOFT:
4091 case RENDERPATH_GLES2:
4092 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4093 Cvar_SetValueQuick(&gl_combine, 1);
4094 Cvar_SetValueQuick(&r_glsl, 1);
4095 r_loadnormalmap = true;
4098 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4099 if (vid.support.arb_uniform_buffer_object)
4100 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4103 case RENDERPATH_GL13:
4104 case RENDERPATH_GLES1:
4105 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4106 Cvar_SetValueQuick(&gl_combine, 1);
4107 Cvar_SetValueQuick(&r_glsl, 0);
4108 r_loadnormalmap = false;
4109 r_loadgloss = false;
4112 case RENDERPATH_GL11:
4113 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4114 Cvar_SetValueQuick(&gl_combine, 0);
4115 Cvar_SetValueQuick(&r_glsl, 0);
4116 r_loadnormalmap = false;
4117 r_loadgloss = false;
4123 R_FrameData_Reset();
4124 R_BufferData_Reset();
4128 memset(r_queries, 0, sizeof(r_queries));
4130 r_qwskincache = NULL;
4131 r_qwskincache_size = 0;
4133 // due to caching of texture_t references, the collision cache must be reset
4134 Collision_Cache_Reset(true);
4136 // set up r_skinframe loading system for textures
4137 memset(&r_skinframe, 0, sizeof(r_skinframe));
4138 r_skinframe.loadsequence = 1;
4139 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4141 r_main_texturepool = R_AllocTexturePool();
4142 R_BuildBlankTextures();
4144 if (vid.support.arb_texture_cube_map)
4147 R_BuildNormalizationCube();
4149 r_texture_fogattenuation = NULL;
4150 r_texture_fogheighttexture = NULL;
4151 r_texture_gammaramps = NULL;
4152 //r_texture_fogintensity = NULL;
4153 memset(&r_fb, 0, sizeof(r_fb));
4154 r_glsl_permutation = NULL;
4155 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4156 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4158 r_hlsl_permutation = NULL;
4159 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4160 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4162 memset(&r_svbsp, 0, sizeof (r_svbsp));
4164 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4165 r_texture_numcubemaps = 0;
4167 r_refdef.fogmasktable_density = 0;
4170 // For Steelstorm Android
4171 // FIXME CACHE the program and reload
4172 // FIXME see possible combinations for SS:BR android
4173 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4174 R_SetupShader_SetPermutationGLSL(0, 12);
4175 R_SetupShader_SetPermutationGLSL(0, 13);
4176 R_SetupShader_SetPermutationGLSL(0, 8388621);
4177 R_SetupShader_SetPermutationGLSL(3, 0);
4178 R_SetupShader_SetPermutationGLSL(3, 2048);
4179 R_SetupShader_SetPermutationGLSL(5, 0);
4180 R_SetupShader_SetPermutationGLSL(5, 2);
4181 R_SetupShader_SetPermutationGLSL(5, 2048);
4182 R_SetupShader_SetPermutationGLSL(5, 8388608);
4183 R_SetupShader_SetPermutationGLSL(11, 1);
4184 R_SetupShader_SetPermutationGLSL(11, 2049);
4185 R_SetupShader_SetPermutationGLSL(11, 8193);
4186 R_SetupShader_SetPermutationGLSL(11, 10241);
4187 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4191 static void gl_main_shutdown(void)
4194 R_FrameData_Reset();
4195 R_BufferData_Reset();
4197 R_Main_FreeViewCache();
4199 switch(vid.renderpath)
4201 case RENDERPATH_GL11:
4202 case RENDERPATH_GL13:
4203 case RENDERPATH_GL20:
4204 case RENDERPATH_GLES1:
4205 case RENDERPATH_GLES2:
4206 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4208 qglDeleteQueriesARB(r_maxqueries, r_queries);
4211 case RENDERPATH_D3D9:
4212 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4214 case RENDERPATH_D3D10:
4215 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4217 case RENDERPATH_D3D11:
4218 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4220 case RENDERPATH_SOFT:
4226 memset(r_queries, 0, sizeof(r_queries));
4228 r_qwskincache = NULL;
4229 r_qwskincache_size = 0;
4231 // clear out the r_skinframe state
4232 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4233 memset(&r_skinframe, 0, sizeof(r_skinframe));
4236 Mem_Free(r_svbsp.nodes);
4237 memset(&r_svbsp, 0, sizeof (r_svbsp));
4238 R_FreeTexturePool(&r_main_texturepool);
4239 loadingscreentexture = NULL;
4240 r_texture_blanknormalmap = NULL;
4241 r_texture_white = NULL;
4242 r_texture_grey128 = NULL;
4243 r_texture_black = NULL;
4244 r_texture_whitecube = NULL;
4245 r_texture_normalizationcube = NULL;
4246 r_texture_fogattenuation = NULL;
4247 r_texture_fogheighttexture = NULL;
4248 r_texture_gammaramps = NULL;
4249 r_texture_numcubemaps = 0;
4250 //r_texture_fogintensity = NULL;
4251 memset(&r_fb, 0, sizeof(r_fb));
4254 r_glsl_permutation = NULL;
4255 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4256 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4258 r_hlsl_permutation = NULL;
4259 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4260 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4264 static void gl_main_newmap(void)
4266 // FIXME: move this code to client
4267 char *entities, entname[MAX_QPATH];
4269 Mem_Free(r_qwskincache);
4270 r_qwskincache = NULL;
4271 r_qwskincache_size = 0;
4274 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4275 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4277 CL_ParseEntityLump(entities);
4281 if (cl.worldmodel->brush.entities)
4282 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4284 R_Main_FreeViewCache();
4286 R_FrameData_Reset();
4287 R_BufferData_Reset();
4290 void GL_Main_Init(void)
4293 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4294 R_InitShaderModeInfo();
4296 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4297 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4298 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4299 if (gamemode == GAME_NEHAHRA)
4301 Cvar_RegisterVariable (&gl_fogenable);
4302 Cvar_RegisterVariable (&gl_fogdensity);
4303 Cvar_RegisterVariable (&gl_fogred);
4304 Cvar_RegisterVariable (&gl_foggreen);
4305 Cvar_RegisterVariable (&gl_fogblue);
4306 Cvar_RegisterVariable (&gl_fogstart);
4307 Cvar_RegisterVariable (&gl_fogend);
4308 Cvar_RegisterVariable (&gl_skyclip);
4310 Cvar_RegisterVariable(&r_motionblur);
4311 Cvar_RegisterVariable(&r_damageblur);
4312 Cvar_RegisterVariable(&r_motionblur_averaging);
4313 Cvar_RegisterVariable(&r_motionblur_randomize);
4314 Cvar_RegisterVariable(&r_motionblur_minblur);
4315 Cvar_RegisterVariable(&r_motionblur_maxblur);
4316 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4317 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4318 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4319 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4320 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4321 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4322 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4323 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4324 Cvar_RegisterVariable(&r_equalize_entities_by);
4325 Cvar_RegisterVariable(&r_equalize_entities_to);
4326 Cvar_RegisterVariable(&r_depthfirst);
4327 Cvar_RegisterVariable(&r_useinfinitefarclip);
4328 Cvar_RegisterVariable(&r_farclip_base);
4329 Cvar_RegisterVariable(&r_farclip_world);
4330 Cvar_RegisterVariable(&r_nearclip);
4331 Cvar_RegisterVariable(&r_deformvertexes);
4332 Cvar_RegisterVariable(&r_transparent);
4333 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4334 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4335 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4336 Cvar_RegisterVariable(&r_showoverdraw);
4337 Cvar_RegisterVariable(&r_showbboxes);
4338 Cvar_RegisterVariable(&r_showbboxes_client);
4339 Cvar_RegisterVariable(&r_showsurfaces);
4340 Cvar_RegisterVariable(&r_showtris);
4341 Cvar_RegisterVariable(&r_shownormals);
4342 Cvar_RegisterVariable(&r_showlighting);
4343 Cvar_RegisterVariable(&r_showshadowvolumes);
4344 Cvar_RegisterVariable(&r_showcollisionbrushes);
4345 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4346 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4347 Cvar_RegisterVariable(&r_showdisabledepthtest);
4348 Cvar_RegisterVariable(&r_drawportals);
4349 Cvar_RegisterVariable(&r_drawentities);
4350 Cvar_RegisterVariable(&r_draw2d);
4351 Cvar_RegisterVariable(&r_drawworld);
4352 Cvar_RegisterVariable(&r_cullentities_trace);
4353 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4354 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4355 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4356 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4357 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4358 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4359 Cvar_RegisterVariable(&r_sortentities);
4360 Cvar_RegisterVariable(&r_drawviewmodel);
4361 Cvar_RegisterVariable(&r_drawexteriormodel);
4362 Cvar_RegisterVariable(&r_speeds);
4363 Cvar_RegisterVariable(&r_fullbrights);
4364 Cvar_RegisterVariable(&r_wateralpha);
4365 Cvar_RegisterVariable(&r_dynamic);
4366 Cvar_RegisterVariable(&r_fakelight);
4367 Cvar_RegisterVariable(&r_fakelight_intensity);
4368 Cvar_RegisterVariable(&r_fullbright_directed);
4369 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4370 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4371 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4372 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4373 Cvar_RegisterVariable(&r_fullbright);
4374 Cvar_RegisterVariable(&r_shadows);
4375 Cvar_RegisterVariable(&r_shadows_darken);
4376 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4377 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4378 Cvar_RegisterVariable(&r_shadows_throwdistance);
4379 Cvar_RegisterVariable(&r_shadows_throwdirection);
4380 Cvar_RegisterVariable(&r_shadows_focus);
4381 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4382 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4383 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4384 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4385 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4386 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4387 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4388 Cvar_RegisterVariable(&r_fog_exp2);
4389 Cvar_RegisterVariable(&r_fog_clear);
4390 Cvar_RegisterVariable(&r_drawfog);
4391 Cvar_RegisterVariable(&r_transparentdepthmasking);
4392 Cvar_RegisterVariable(&r_transparent_sortmindist);
4393 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4394 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4395 Cvar_RegisterVariable(&r_texture_dds_load);
4396 Cvar_RegisterVariable(&r_texture_dds_save);
4397 Cvar_RegisterVariable(&r_textureunits);
4398 Cvar_RegisterVariable(&gl_combine);
4399 Cvar_RegisterVariable(&r_usedepthtextures);
4400 Cvar_RegisterVariable(&r_viewfbo);
4401 Cvar_RegisterVariable(&r_viewscale);
4402 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4403 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4404 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4405 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4406 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4407 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4408 Cvar_RegisterVariable(&r_glsl);
4409 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4410 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4411 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4412 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4413 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4414 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4415 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4416 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4417 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4418 Cvar_RegisterVariable(&r_glsl_postprocess);
4419 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4420 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4421 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4422 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4423 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4424 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4425 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4426 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4427 Cvar_RegisterVariable(&r_celshading);
4428 Cvar_RegisterVariable(&r_celoutlines);
4430 Cvar_RegisterVariable(&r_water);
4431 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4432 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4433 Cvar_RegisterVariable(&r_water_clippingplanebias);
4434 Cvar_RegisterVariable(&r_water_refractdistort);
4435 Cvar_RegisterVariable(&r_water_reflectdistort);
4436 Cvar_RegisterVariable(&r_water_scissormode);
4437 Cvar_RegisterVariable(&r_water_lowquality);
4438 Cvar_RegisterVariable(&r_water_hideplayer);
4439 Cvar_RegisterVariable(&r_water_fbo);
4441 Cvar_RegisterVariable(&r_lerpsprites);
4442 Cvar_RegisterVariable(&r_lerpmodels);
4443 Cvar_RegisterVariable(&r_lerplightstyles);
4444 Cvar_RegisterVariable(&r_waterscroll);
4445 Cvar_RegisterVariable(&r_bloom);
4446 Cvar_RegisterVariable(&r_bloom_colorscale);
4447 Cvar_RegisterVariable(&r_bloom_brighten);
4448 Cvar_RegisterVariable(&r_bloom_blur);
4449 Cvar_RegisterVariable(&r_bloom_resolution);
4450 Cvar_RegisterVariable(&r_bloom_colorexponent);
4451 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4452 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4453 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4454 Cvar_RegisterVariable(&r_hdr_glowintensity);
4455 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4456 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4457 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4458 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4459 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4460 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4461 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4462 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4463 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4464 Cvar_RegisterVariable(&developer_texturelogging);
4465 Cvar_RegisterVariable(&gl_lightmaps);
4466 Cvar_RegisterVariable(&r_test);
4467 Cvar_RegisterVariable(&r_batch_multidraw);
4468 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4469 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4470 Cvar_RegisterVariable(&r_glsl_skeletal);
4471 Cvar_RegisterVariable(&r_glsl_saturation);
4472 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4473 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4474 Cvar_RegisterVariable(&r_framedatasize);
4475 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4476 Cvar_RegisterVariable(&r_buffermegs[i]);
4477 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4478 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4479 Cvar_SetValue("r_fullbrights", 0);
4480 #ifdef DP_MOBILETOUCH
4481 // GLES devices have terrible depth precision in general, so...
4482 Cvar_SetValueQuick(&r_nearclip, 4);
4483 Cvar_SetValueQuick(&r_farclip_base, 4096);
4484 Cvar_SetValueQuick(&r_farclip_world, 0);
4485 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4487 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4490 void Render_Init(void)
4503 R_LightningBeams_Init();
4513 extern char *ENGINE_EXTENSIONS;
4516 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4517 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4518 gl_version = (const char *)qglGetString(GL_VERSION);
4519 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4523 if (!gl_platformextensions)
4524 gl_platformextensions = "";
4526 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4527 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4528 Con_Printf("GL_VERSION: %s\n", gl_version);
4529 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4530 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4532 VID_CheckExtensions();
4534 // LordHavoc: report supported extensions
4536 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4538 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4541 // clear to black (loading plaque will be seen over this)
4542 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4546 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4550 if (r_trippy.integer)
4552 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4554 p = r_refdef.view.frustum + i;
4559 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4563 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4567 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4571 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4575 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4579 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4583 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4587 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4595 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4599 if (r_trippy.integer)
4601 for (i = 0;i < numplanes;i++)
4608 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4612 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4616 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4620 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4624 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4628 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4632 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4636 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4644 //==================================================================================
4646 // LordHavoc: this stores temporary data used within the same frame
4648 typedef struct r_framedata_mem_s
4650 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4651 size_t size; // how much usable space
4652 size_t current; // how much space in use
4653 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4654 size_t wantedsize; // how much space was allocated
4655 unsigned char *data; // start of real data (16byte aligned)
4659 static r_framedata_mem_t *r_framedata_mem;
4661 void R_FrameData_Reset(void)
4663 while (r_framedata_mem)
4665 r_framedata_mem_t *next = r_framedata_mem->purge;
4666 Mem_Free(r_framedata_mem);
4667 r_framedata_mem = next;
4671 static void R_FrameData_Resize(qboolean mustgrow)
4674 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4675 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4676 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4678 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4679 newmem->wantedsize = wantedsize;
4680 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4681 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4682 newmem->current = 0;
4684 newmem->purge = r_framedata_mem;
4685 r_framedata_mem = newmem;
4689 void R_FrameData_NewFrame(void)
4691 R_FrameData_Resize(false);
4692 if (!r_framedata_mem)
4694 // if we ran out of space on the last frame, free the old memory now
4695 while (r_framedata_mem->purge)
4697 // repeatedly remove the second item in the list, leaving only head
4698 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4699 Mem_Free(r_framedata_mem->purge);
4700 r_framedata_mem->purge = next;
4702 // reset the current mem pointer
4703 r_framedata_mem->current = 0;
4704 r_framedata_mem->mark = 0;
4707 void *R_FrameData_Alloc(size_t size)
4712 // align to 16 byte boundary - the data pointer is already aligned, so we
4713 // only need to ensure the size of every allocation is also aligned
4714 size = (size + 15) & ~15;
4716 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4718 // emergency - we ran out of space, allocate more memory
4719 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4720 newvalue = r_framedatasize.value * 2.0f;
4721 // 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
4722 if (sizeof(size_t) >= 8)
4723 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4725 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4726 // this might not be a growing it, but we'll allocate another buffer every time
4727 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4728 R_FrameData_Resize(true);
4731 data = r_framedata_mem->data + r_framedata_mem->current;
4732 r_framedata_mem->current += size;
4734 // count the usage for stats
4735 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4736 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4738 return (void *)data;
4741 void *R_FrameData_Store(size_t size, void *data)
4743 void *d = R_FrameData_Alloc(size);
4745 memcpy(d, data, size);
4749 void R_FrameData_SetMark(void)
4751 if (!r_framedata_mem)
4753 r_framedata_mem->mark = r_framedata_mem->current;
4756 void R_FrameData_ReturnToMark(void)
4758 if (!r_framedata_mem)
4760 r_framedata_mem->current = r_framedata_mem->mark;
4763 //==================================================================================
4765 // avoid reusing the same buffer objects on consecutive frames
4766 #define R_BUFFERDATA_CYCLE 3
4768 typedef struct r_bufferdata_buffer_s
4770 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4771 size_t size; // how much usable space
4772 size_t current; // how much space in use
4773 r_meshbuffer_t *buffer; // the buffer itself
4775 r_bufferdata_buffer_t;
4777 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4778 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4780 /// frees all dynamic buffers
4781 void R_BufferData_Reset(void)
4784 r_bufferdata_buffer_t **p, *mem;
4785 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4787 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4790 p = &r_bufferdata_buffer[cycle][type];
4796 R_Mesh_DestroyMeshBuffer(mem->buffer);
4803 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4804 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4806 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4808 float newvalue = r_buffermegs[type].value;
4810 // increase the cvar if we have to (but only if we already have a mem)
4811 if (mustgrow && mem)
4813 newvalue = bound(0.25f, newvalue, 256.0f);
4814 while (newvalue * 1024*1024 < minsize)
4817 // clamp the cvar to valid range
4818 newvalue = bound(0.25f, newvalue, 256.0f);
4819 if (r_buffermegs[type].value != newvalue)
4820 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4822 // calculate size in bytes
4823 size = (size_t)(newvalue * 1024*1024);
4824 size = bound(131072, size, 256*1024*1024);
4826 // allocate a new buffer if the size is different (purge old one later)
4827 // or if we were told we must grow the buffer
4828 if (!mem || mem->size != size || mustgrow)
4830 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4833 if (type == R_BUFFERDATA_VERTEX)
4834 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4835 else if (type == R_BUFFERDATA_INDEX16)
4836 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4837 else if (type == R_BUFFERDATA_INDEX32)
4838 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4839 else if (type == R_BUFFERDATA_UNIFORM)
4840 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4841 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4842 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4846 void R_BufferData_NewFrame(void)
4849 r_bufferdata_buffer_t **p, *mem;
4850 // cycle to the next frame's buffers
4851 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4852 // if we ran out of space on the last time we used these buffers, free the old memory now
4853 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4855 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4857 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4858 // free all but the head buffer, this is how we recycle obsolete
4859 // buffers after they are no longer in use
4860 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4866 R_Mesh_DestroyMeshBuffer(mem->buffer);
4869 // reset the current offset
4870 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4875 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4877 r_bufferdata_buffer_t *mem;
4881 *returnbufferoffset = 0;
4883 // align size to a byte boundary appropriate for the buffer type, this
4884 // makes all allocations have aligned start offsets
4885 if (type == R_BUFFERDATA_UNIFORM)
4886 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4888 padsize = (datasize + 15) & ~15;
4890 // if we ran out of space in this buffer we must allocate a new one
4891 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)
4892 R_BufferData_Resize(type, true, padsize);
4894 // if the resize did not give us enough memory, fail
4895 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)
4896 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4898 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4899 offset = (int)mem->current;
4900 mem->current += padsize;
4902 // upload the data to the buffer at the chosen offset
4904 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4905 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4907 // count the usage for stats
4908 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4909 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4911 // return the buffer offset
4912 *returnbufferoffset = offset;
4917 //==================================================================================
4919 // LordHavoc: animcache originally written by Echon, rewritten since then
4922 * Animation cache prevents re-generating mesh data for an animated model
4923 * multiple times in one frame for lighting, shadowing, reflections, etc.
4926 void R_AnimCache_Free(void)
4930 void R_AnimCache_ClearCache(void)
4933 entity_render_t *ent;
4935 for (i = 0;i < r_refdef.scene.numentities;i++)
4937 ent = r_refdef.scene.entities[i];
4938 ent->animcache_vertex3f = NULL;
4939 ent->animcache_vertex3f_vertexbuffer = NULL;
4940 ent->animcache_vertex3f_bufferoffset = 0;
4941 ent->animcache_normal3f = NULL;
4942 ent->animcache_normal3f_vertexbuffer = NULL;
4943 ent->animcache_normal3f_bufferoffset = 0;
4944 ent->animcache_svector3f = NULL;
4945 ent->animcache_svector3f_vertexbuffer = NULL;
4946 ent->animcache_svector3f_bufferoffset = 0;
4947 ent->animcache_tvector3f = NULL;
4948 ent->animcache_tvector3f_vertexbuffer = NULL;
4949 ent->animcache_tvector3f_bufferoffset = 0;
4950 ent->animcache_vertexmesh = NULL;
4951 ent->animcache_vertexmesh_vertexbuffer = NULL;
4952 ent->animcache_vertexmesh_bufferoffset = 0;
4953 ent->animcache_skeletaltransform3x4 = NULL;
4954 ent->animcache_skeletaltransform3x4buffer = NULL;
4955 ent->animcache_skeletaltransform3x4offset = 0;
4956 ent->animcache_skeletaltransform3x4size = 0;
4960 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4964 // check if we need the meshbuffers
4965 if (!vid.useinterleavedarrays)
4968 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4969 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4970 // TODO: upload vertexbuffer?
4971 if (ent->animcache_vertexmesh)
4973 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4974 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4975 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4976 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4977 for (i = 0;i < numvertices;i++)
4978 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4979 if (ent->animcache_svector3f)
4980 for (i = 0;i < numvertices;i++)
4981 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4982 if (ent->animcache_tvector3f)
4983 for (i = 0;i < numvertices;i++)
4984 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4985 if (ent->animcache_normal3f)
4986 for (i = 0;i < numvertices;i++)
4987 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4991 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4993 dp_model_t *model = ent->model;
4996 // see if this ent is worth caching
4997 if (!model || !model->Draw || !model->AnimateVertices)
4999 // nothing to cache if it contains no animations and has no skeleton
5000 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5002 // see if it is already cached for gpuskeletal
5003 if (ent->animcache_skeletaltransform3x4)
5005 // see if it is already cached as a mesh
5006 if (ent->animcache_vertex3f)
5008 // check if we need to add normals or tangents
5009 if (ent->animcache_normal3f)
5010 wantnormals = false;
5011 if (ent->animcache_svector3f)
5012 wanttangents = false;
5013 if (!wantnormals && !wanttangents)
5017 // check which kind of cache we need to generate
5018 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5020 // cache the skeleton so the vertex shader can use it
5021 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5022 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5023 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5024 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5025 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
5026 // note: this can fail if the buffer is at the grow limit
5027 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5028 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5030 else if (ent->animcache_vertex3f)
5032 // mesh was already cached but we may need to add normals/tangents
5033 // (this only happens with multiple views, reflections, cameras, etc)
5034 if (wantnormals || wanttangents)
5036 numvertices = model->surfmesh.num_vertices;
5038 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5041 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5042 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5044 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5045 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5046 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5047 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5048 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5053 // generate mesh cache
5054 numvertices = model->surfmesh.num_vertices;
5055 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5057 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5060 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5061 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5063 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5064 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5065 if (wantnormals || wanttangents)
5067 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5068 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5069 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5071 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5072 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5073 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5078 void R_AnimCache_CacheVisibleEntities(void)
5081 qboolean wantnormals = true;
5082 qboolean wanttangents = !r_showsurfaces.integer;
5084 switch(vid.renderpath)
5086 case RENDERPATH_GL20:
5087 case RENDERPATH_D3D9:
5088 case RENDERPATH_D3D10:
5089 case RENDERPATH_D3D11:
5090 case RENDERPATH_GLES2:
5092 case RENDERPATH_GL11:
5093 case RENDERPATH_GL13:
5094 case RENDERPATH_GLES1:
5095 wanttangents = false;
5097 case RENDERPATH_SOFT:
5101 if (r_shownormals.integer)
5102 wanttangents = wantnormals = true;
5104 // TODO: thread this
5105 // NOTE: R_PrepareRTLights() also caches entities
5107 for (i = 0;i < r_refdef.scene.numentities;i++)
5108 if (r_refdef.viewcache.entityvisible[i])
5109 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5112 //==================================================================================
5114 extern cvar_t r_overheadsprites_pushback;
5116 static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal)
5120 VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value);
5121 VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value);
5123 // Use cl.viewangles and not r_refdef.view.forward here so it is the
5124 // same for all stereo views, and to better handle pitches outside
5125 // [-90, 90] (in_pitch_* cvars allow that).
5126 VectorCopy(cl.viewangles, angles);
5127 if (r_fullbright_directed_pitch_relative.integer) {
5128 angles[PITCH] += r_fullbright_directed_pitch.value;
5130 angles[PITCH] = r_fullbright_directed_pitch.value;
5132 AngleVectors(angles, worldspacenormal, NULL, NULL);
5133 VectorNegate(worldspacenormal, worldspacenormal);
5136 static void R_View_UpdateEntityLighting (void)
5139 entity_render_t *ent;
5140 vec3_t tempdiffusenormal, avg;
5141 vec_t f, fa, fd, fdd;
5142 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5144 for (i = 0;i < r_refdef.scene.numentities;i++)
5146 ent = r_refdef.scene.entities[i];
5148 // skip unseen models
5149 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5153 if (ent->model && ent->model == cl.worldmodel)
5155 // TODO: use modellight for r_ambient settings on world?
5156 // The logic here currently matches RSurf_ActiveWorldEntity.
5157 if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit))
5159 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5160 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5161 if(VectorLength2(ent->modellight_lightdir) == 0)
5162 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5163 VectorNormalize(ent->modellight_lightdir);
5167 VectorSet(ent->modellight_ambient, 0, 0, 0);
5168 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5169 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5174 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5176 // aleady updated by CSQC
5177 // TODO: force modellight on BSP models in this case?
5178 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5182 // fetch the lighting from the worldmodel data
5183 VectorClear(ent->modellight_ambient);
5184 VectorClear(ent->modellight_diffuse);
5185 VectorClear(tempdiffusenormal);
5186 if (ent->flags & RENDER_LIGHT)
5189 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5191 // complete lightning for lit sprites
5192 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5193 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5195 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5196 org[2] = org[2] + r_overheadsprites_pushback.value;
5197 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5199 else if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
5201 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5203 else if (r_fullbright_directed.integer)
5205 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5209 VectorSet(ent->modellight_ambient, 1, 1, 1);
5212 if(ent->flags & RENDER_EQUALIZE)
5214 // first fix up ambient lighting...
5215 if(r_equalize_entities_minambient.value > 0)
5217 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5220 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5221 if(fa < r_equalize_entities_minambient.value * fd)
5224 // fa'/fd' = minambient
5225 // fa'+0.25*fd' = fa+0.25*fd
5227 // fa' = fd' * minambient
5228 // fd'*(0.25+minambient) = fa+0.25*fd
5230 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5231 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5233 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5234 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5235 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5236 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5241 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5243 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5244 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5248 // adjust brightness and saturation to target
5249 avg[0] = avg[1] = avg[2] = fa / f;
5250 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5251 avg[0] = avg[1] = avg[2] = fd / f;
5252 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5259 // EF_FULLBRIGHT entity.
5260 if (r_fullbright_directed.integer)
5262 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5266 VectorSet(ent->modellight_ambient, 1, 1, 1);
5271 // move the light direction into modelspace coordinates for lighting code
5272 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5273 if(VectorLength2(ent->modellight_lightdir) == 0)
5274 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5275 VectorNormalize(ent->modellight_lightdir);
5279 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5282 vec3_t eyemins, eyemaxs;
5283 vec3_t boxmins, boxmaxs;
5286 dp_model_t *model = r_refdef.scene.worldmodel;
5287 static vec3_t positions[] = {
5288 { 0.5f, 0.5f, 0.5f },
5289 { 0.0f, 0.0f, 0.0f },
5290 { 0.0f, 0.0f, 1.0f },
5291 { 0.0f, 1.0f, 0.0f },
5292 { 0.0f, 1.0f, 1.0f },
5293 { 1.0f, 0.0f, 0.0f },
5294 { 1.0f, 0.0f, 1.0f },
5295 { 1.0f, 1.0f, 0.0f },
5296 { 1.0f, 1.0f, 1.0f },
5299 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5303 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5304 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5307 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5310 // expand the eye box a little
5311 eyemins[0] = eye[0] - eyejitter;
5312 eyemaxs[0] = eye[0] + eyejitter;
5313 eyemins[1] = eye[1] - eyejitter;
5314 eyemaxs[1] = eye[1] + eyejitter;
5315 eyemins[2] = eye[2] - eyejitter;
5316 eyemaxs[2] = eye[2] + eyejitter;
5317 // expand the box a little
5318 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5319 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5320 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5321 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5322 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5323 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5325 // return true if eye overlaps enlarged box
5326 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5329 // try specific positions in the box first - note that these can be cached
5330 if (r_cullentities_trace_entityocclusion.integer)
5332 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5334 VectorCopy(eye, start);
5335 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5336 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5337 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5338 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5339 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5340 // not picky - if the trace ended anywhere in the box we're good
5341 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5345 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5348 // try various random positions
5349 for (i = 0; i < numsamples; i++)
5351 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5352 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5353 if (r_cullentities_trace_entityocclusion.integer)
5355 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5356 // not picky - if the trace ended anywhere in the box we're good
5357 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5360 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5368 static void R_View_UpdateEntityVisible (void)
5373 entity_render_t *ent;
5375 if (r_refdef.envmap || r_fb.water.hideplayer)
5376 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5377 else if (chase_active.integer || r_fb.water.renderingscene)
5378 renderimask = RENDER_VIEWMODEL;
5380 renderimask = RENDER_EXTERIORMODEL;
5381 if (!r_drawviewmodel.integer)
5382 renderimask |= RENDER_VIEWMODEL;
5383 if (!r_drawexteriormodel.integer)
5384 renderimask |= RENDER_EXTERIORMODEL;
5385 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5386 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5388 // worldmodel can check visibility
5389 for (i = 0;i < r_refdef.scene.numentities;i++)
5391 ent = r_refdef.scene.entities[i];
5392 if (!(ent->flags & renderimask))
5393 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)))
5394 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))
5395 r_refdef.viewcache.entityvisible[i] = true;
5400 // no worldmodel or it can't check visibility
5401 for (i = 0;i < r_refdef.scene.numentities;i++)
5403 ent = r_refdef.scene.entities[i];
5404 if (!(ent->flags & renderimask))
5405 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)))
5406 r_refdef.viewcache.entityvisible[i] = true;
5409 if (r_cullentities_trace.integer)
5411 for (i = 0;i < r_refdef.scene.numentities;i++)
5413 if (!r_refdef.viewcache.entityvisible[i])
5415 ent = r_refdef.scene.entities[i];
5416 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5418 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5419 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5420 ent->last_trace_visibility = realtime;
5421 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5422 r_refdef.viewcache.entityvisible[i] = 0;
5428 /// only used if skyrendermasked, and normally returns false
5429 static int R_DrawBrushModelsSky (void)
5432 entity_render_t *ent;
5435 for (i = 0;i < r_refdef.scene.numentities;i++)
5437 if (!r_refdef.viewcache.entityvisible[i])
5439 ent = r_refdef.scene.entities[i];
5440 if (!ent->model || !ent->model->DrawSky)
5442 ent->model->DrawSky(ent);
5448 static void R_DrawNoModel(entity_render_t *ent);
5449 static void R_DrawModels(void)
5452 entity_render_t *ent;
5454 for (i = 0;i < r_refdef.scene.numentities;i++)
5456 if (!r_refdef.viewcache.entityvisible[i])
5458 ent = r_refdef.scene.entities[i];
5459 r_refdef.stats[r_stat_entities]++;
5461 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5464 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5465 Con_Printf("R_DrawModels\n");
5466 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]);
5467 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);
5468 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);
5471 if (ent->model && ent->model->Draw != NULL)
5472 ent->model->Draw(ent);
5478 static void R_DrawModelsDepth(void)
5481 entity_render_t *ent;
5483 for (i = 0;i < r_refdef.scene.numentities;i++)
5485 if (!r_refdef.viewcache.entityvisible[i])
5487 ent = r_refdef.scene.entities[i];
5488 if (ent->model && ent->model->DrawDepth != NULL)
5489 ent->model->DrawDepth(ent);
5493 static void R_DrawModelsDebug(void)
5496 entity_render_t *ent;
5498 for (i = 0;i < r_refdef.scene.numentities;i++)
5500 if (!r_refdef.viewcache.entityvisible[i])
5502 ent = r_refdef.scene.entities[i];
5503 if (ent->model && ent->model->DrawDebug != NULL)
5504 ent->model->DrawDebug(ent);
5508 static void R_DrawModelsAddWaterPlanes(void)
5511 entity_render_t *ent;
5513 for (i = 0;i < r_refdef.scene.numentities;i++)
5515 if (!r_refdef.viewcache.entityvisible[i])
5517 ent = r_refdef.scene.entities[i];
5518 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5519 ent->model->DrawAddWaterPlanes(ent);
5523 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}};
5525 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5527 if (r_hdr_irisadaptation.integer)
5532 vec3_t diffusenormal;
5534 vec_t brightness = 0.0f;
5539 VectorCopy(r_refdef.view.forward, forward);
5540 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5542 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5543 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5544 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5545 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5546 d = DotProduct(forward, diffusenormal);
5547 brightness += VectorLength(ambient);
5549 brightness += d * VectorLength(diffuse);
5551 brightness *= 1.0f / c;
5552 brightness += 0.00001f; // make sure it's never zero
5553 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5554 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5555 current = r_hdr_irisadaptation_value.value;
5557 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5558 else if (current > goal)
5559 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5560 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5561 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5563 else if (r_hdr_irisadaptation_value.value != 1.0f)
5564 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5567 static void R_View_SetFrustum(const int *scissor)
5570 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5571 vec3_t forward, left, up, origin, v;
5575 // flipped x coordinates (because x points left here)
5576 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5577 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5579 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5580 switch(vid.renderpath)
5582 case RENDERPATH_D3D9:
5583 case RENDERPATH_D3D10:
5584 case RENDERPATH_D3D11:
5585 // non-flipped y coordinates
5586 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5587 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5589 case RENDERPATH_SOFT:
5590 case RENDERPATH_GL11:
5591 case RENDERPATH_GL13:
5592 case RENDERPATH_GL20:
5593 case RENDERPATH_GLES1:
5594 case RENDERPATH_GLES2:
5595 // non-flipped y coordinates
5596 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5597 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5602 // we can't trust r_refdef.view.forward and friends in reflected scenes
5603 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5606 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5607 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5608 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5609 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5610 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5611 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5612 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5613 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5614 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5615 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5616 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5617 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5621 zNear = r_refdef.nearclip;
5622 nudge = 1.0 - 1.0 / (1<<23);
5623 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5624 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5625 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5626 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5627 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5628 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5629 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5630 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5636 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5637 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5638 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5639 r_refdef.view.frustum[0].dist = m[15] - m[12];
5641 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5642 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5643 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5644 r_refdef.view.frustum[1].dist = m[15] + m[12];
5646 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5647 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5648 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5649 r_refdef.view.frustum[2].dist = m[15] - m[13];
5651 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5652 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5653 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5654 r_refdef.view.frustum[3].dist = m[15] + m[13];
5656 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5657 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5658 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5659 r_refdef.view.frustum[4].dist = m[15] - m[14];
5661 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5662 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5663 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5664 r_refdef.view.frustum[5].dist = m[15] + m[14];
5667 if (r_refdef.view.useperspective)
5669 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5670 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]);
5671 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]);
5672 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]);
5673 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]);
5675 // then the normals from the corners relative to origin
5676 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5677 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5678 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5679 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5681 // in a NORMAL view, forward cross left == up
5682 // in a REFLECTED view, forward cross left == down
5683 // so our cross products above need to be adjusted for a left handed coordinate system
5684 CrossProduct(forward, left, v);
5685 if(DotProduct(v, up) < 0)
5687 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5688 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5689 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5690 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5693 // Leaving those out was a mistake, those were in the old code, and they
5694 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5695 // I couldn't reproduce it after adding those normalizations. --blub
5696 VectorNormalize(r_refdef.view.frustum[0].normal);
5697 VectorNormalize(r_refdef.view.frustum[1].normal);
5698 VectorNormalize(r_refdef.view.frustum[2].normal);
5699 VectorNormalize(r_refdef.view.frustum[3].normal);
5701 // make the corners absolute
5702 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5703 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5704 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5705 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5708 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5710 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5711 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5712 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5713 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5714 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5718 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5719 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5720 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5721 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5722 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5723 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5724 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5725 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5726 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5727 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5729 r_refdef.view.numfrustumplanes = 5;
5731 if (r_refdef.view.useclipplane)
5733 r_refdef.view.numfrustumplanes = 6;
5734 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5737 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5738 PlaneClassify(r_refdef.view.frustum + i);
5740 // LordHavoc: note to all quake engine coders, Quake had a special case
5741 // for 90 degrees which assumed a square view (wrong), so I removed it,
5742 // Quake2 has it disabled as well.
5744 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5745 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5746 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5747 //PlaneClassify(&frustum[0]);
5749 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5750 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5751 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5752 //PlaneClassify(&frustum[1]);
5754 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5755 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5756 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5757 //PlaneClassify(&frustum[2]);
5759 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5760 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5761 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5762 //PlaneClassify(&frustum[3]);
5765 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5766 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5767 //PlaneClassify(&frustum[4]);
5770 static void R_View_UpdateWithScissor(const int *myscissor)
5772 R_Main_ResizeViewCache();
5773 R_View_SetFrustum(myscissor);
5774 R_View_WorldVisibility(r_refdef.view.useclipplane);
5775 R_View_UpdateEntityVisible();
5776 R_View_UpdateEntityLighting();
5779 static void R_View_Update(void)
5781 R_Main_ResizeViewCache();
5782 R_View_SetFrustum(NULL);
5783 R_View_WorldVisibility(r_refdef.view.useclipplane);
5784 R_View_UpdateEntityVisible();
5785 R_View_UpdateEntityLighting();
5788 float viewscalefpsadjusted = 1.0f;
5790 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5792 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5793 scale = bound(0.03125f, scale, 1.0f);
5794 *outwidth = (int)ceil(width * scale);
5795 *outheight = (int)ceil(height * scale);
5798 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5800 const float *customclipplane = NULL;
5802 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5803 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5805 // LordHavoc: couldn't figure out how to make this approach the
5806 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5807 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5808 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5809 dist = r_refdef.view.clipplane.dist;
5810 plane[0] = r_refdef.view.clipplane.normal[0];
5811 plane[1] = r_refdef.view.clipplane.normal[1];
5812 plane[2] = r_refdef.view.clipplane.normal[2];
5814 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5817 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5818 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5820 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5821 if (!r_refdef.view.useperspective)
5822 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5823 else if (vid.stencil && r_useinfinitefarclip.integer)
5824 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5826 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5827 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5828 R_SetViewport(&r_refdef.view.viewport);
5829 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5831 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5832 float screenplane[4];
5833 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5834 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5835 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5836 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5837 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5841 void R_EntityMatrix(const matrix4x4_t *matrix)
5843 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5845 gl_modelmatrixchanged = false;
5846 gl_modelmatrix = *matrix;
5847 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5848 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5849 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5850 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5852 switch(vid.renderpath)
5854 case RENDERPATH_D3D9:
5856 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5857 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5860 case RENDERPATH_D3D10:
5861 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5863 case RENDERPATH_D3D11:
5864 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5866 case RENDERPATH_GL11:
5867 case RENDERPATH_GL13:
5868 case RENDERPATH_GLES1:
5870 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5873 case RENDERPATH_SOFT:
5874 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5875 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5877 case RENDERPATH_GL20:
5878 case RENDERPATH_GLES2:
5879 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5880 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5886 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5888 r_viewport_t viewport;
5892 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5893 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, x2, y2, -10, 100, NULL);
5894 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5895 R_SetViewport(&viewport);
5896 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5897 GL_Color(1, 1, 1, 1);
5898 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5899 GL_BlendFunc(GL_ONE, GL_ZERO);
5900 GL_ScissorTest(false);
5901 GL_DepthMask(false);
5902 GL_DepthRange(0, 1);
5903 GL_DepthTest(false);
5904 GL_DepthFunc(GL_LEQUAL);
5905 R_EntityMatrix(&identitymatrix);
5906 R_Mesh_ResetTextureState();
5907 GL_PolygonOffset(0, 0);
5908 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5909 switch(vid.renderpath)
5911 case RENDERPATH_GL11:
5912 case RENDERPATH_GL13:
5913 case RENDERPATH_GL20:
5914 case RENDERPATH_GLES1:
5915 case RENDERPATH_GLES2:
5916 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5918 case RENDERPATH_D3D9:
5919 case RENDERPATH_D3D10:
5920 case RENDERPATH_D3D11:
5921 case RENDERPATH_SOFT:
5924 GL_CullFace(GL_NONE);
5929 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5933 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5936 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5940 R_SetupView(true, fbo, depthtexture, colortexture);
5941 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5942 GL_Color(1, 1, 1, 1);
5943 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5944 GL_BlendFunc(GL_ONE, GL_ZERO);
5945 GL_ScissorTest(true);
5947 GL_DepthRange(0, 1);
5949 GL_DepthFunc(GL_LEQUAL);
5950 R_EntityMatrix(&identitymatrix);
5951 R_Mesh_ResetTextureState();
5952 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5953 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5954 switch(vid.renderpath)
5956 case RENDERPATH_GL11:
5957 case RENDERPATH_GL13:
5958 case RENDERPATH_GL20:
5959 case RENDERPATH_GLES1:
5960 case RENDERPATH_GLES2:
5961 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5963 case RENDERPATH_D3D9:
5964 case RENDERPATH_D3D10:
5965 case RENDERPATH_D3D11:
5966 case RENDERPATH_SOFT:
5969 GL_CullFace(r_refdef.view.cullface_back);
5974 R_RenderView_UpdateViewVectors
5977 void R_RenderView_UpdateViewVectors(void)
5979 // break apart the view matrix into vectors for various purposes
5980 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5981 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5982 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5983 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5984 // make an inverted copy of the view matrix for tracking sprites
5985 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5988 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5989 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5991 static void R_Water_StartFrame(void)
5994 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5995 r_waterstate_waterplane_t *p;
5996 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5998 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6001 switch(vid.renderpath)
6003 case RENDERPATH_GL20:
6004 case RENDERPATH_D3D9:
6005 case RENDERPATH_D3D10:
6006 case RENDERPATH_D3D11:
6007 case RENDERPATH_SOFT:
6008 case RENDERPATH_GLES2:
6010 case RENDERPATH_GL11:
6011 case RENDERPATH_GL13:
6012 case RENDERPATH_GLES1:
6016 // set waterwidth and waterheight to the water resolution that will be
6017 // used (often less than the screen resolution for faster rendering)
6018 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
6020 // calculate desired texture sizes
6021 // can't use water if the card does not support the texture size
6022 if (!r_water.integer || r_showsurfaces.integer)
6023 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
6024 else if (vid.support.arb_texture_non_power_of_two)
6026 texturewidth = waterwidth;
6027 textureheight = waterheight;
6028 camerawidth = waterwidth;
6029 cameraheight = waterheight;
6033 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6034 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6035 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
6036 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
6039 // allocate textures as needed
6040 if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
6042 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6043 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
6045 if (p->texture_refraction)
6046 R_FreeTexture(p->texture_refraction);
6047 p->texture_refraction = NULL;
6048 if (p->fbo_refraction)
6049 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
6050 p->fbo_refraction = 0;
6051 if (p->texture_reflection)
6052 R_FreeTexture(p->texture_reflection);
6053 p->texture_reflection = NULL;
6054 if (p->fbo_reflection)
6055 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6056 p->fbo_reflection = 0;
6057 if (p->texture_camera)
6058 R_FreeTexture(p->texture_camera);
6059 p->texture_camera = NULL;
6061 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6064 memset(&r_fb.water, 0, sizeof(r_fb.water));
6065 r_fb.water.texturewidth = texturewidth;
6066 r_fb.water.textureheight = textureheight;
6067 r_fb.water.camerawidth = camerawidth;
6068 r_fb.water.cameraheight = cameraheight;
6071 if (r_fb.water.texturewidth)
6073 int scaledwidth, scaledheight;
6075 r_fb.water.enabled = true;
6077 // water resolution is usually reduced
6078 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6079 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6080 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6082 // set up variables that will be used in shader setup
6083 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6084 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6085 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6086 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6089 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6090 r_fb.water.numwaterplanes = 0;
6093 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6095 int planeindex, bestplaneindex, vertexindex;
6096 vec3_t mins, maxs, normal, center, v, n;
6097 vec_t planescore, bestplanescore;
6099 r_waterstate_waterplane_t *p;
6100 texture_t *t = R_GetCurrentTexture(surface->texture);
6102 rsurface.texture = t;
6103 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6104 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6105 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6107 // average the vertex normals, find the surface bounds (after deformvertexes)
6108 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6109 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6110 VectorCopy(n, normal);
6111 VectorCopy(v, mins);
6112 VectorCopy(v, maxs);
6113 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6115 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6116 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6117 VectorAdd(normal, n, normal);
6118 mins[0] = min(mins[0], v[0]);
6119 mins[1] = min(mins[1], v[1]);
6120 mins[2] = min(mins[2], v[2]);
6121 maxs[0] = max(maxs[0], v[0]);
6122 maxs[1] = max(maxs[1], v[1]);
6123 maxs[2] = max(maxs[2], v[2]);
6125 VectorNormalize(normal);
6126 VectorMAM(0.5f, mins, 0.5f, maxs, center);
6128 VectorCopy(normal, plane.normal);
6129 VectorNormalize(plane.normal);
6130 plane.dist = DotProduct(center, plane.normal);
6131 PlaneClassify(&plane);
6132 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6134 // skip backfaces (except if nocullface is set)
6135 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6137 VectorNegate(plane.normal, plane.normal);
6139 PlaneClassify(&plane);
6143 // find a matching plane if there is one
6144 bestplaneindex = -1;
6145 bestplanescore = 1048576.0f;
6146 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6148 if(p->camera_entity == t->camera_entity)
6150 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6151 if (bestplaneindex < 0 || bestplanescore > planescore)
6153 bestplaneindex = planeindex;
6154 bestplanescore = planescore;
6158 planeindex = bestplaneindex;
6160 // if this surface does not fit any known plane rendered this frame, add one
6161 if (planeindex < 0 || bestplanescore > 0.001f)
6163 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6165 // store the new plane
6166 planeindex = r_fb.water.numwaterplanes++;
6167 p = r_fb.water.waterplanes + planeindex;
6169 // clear materialflags and pvs
6170 p->materialflags = 0;
6171 p->pvsvalid = false;
6172 p->camera_entity = t->camera_entity;
6173 VectorCopy(mins, p->mins);
6174 VectorCopy(maxs, p->maxs);
6178 // We're totally screwed.
6184 // merge mins/maxs when we're adding this surface to the plane
6185 p = r_fb.water.waterplanes + planeindex;
6186 p->mins[0] = min(p->mins[0], mins[0]);
6187 p->mins[1] = min(p->mins[1], mins[1]);
6188 p->mins[2] = min(p->mins[2], mins[2]);
6189 p->maxs[0] = max(p->maxs[0], maxs[0]);
6190 p->maxs[1] = max(p->maxs[1], maxs[1]);
6191 p->maxs[2] = max(p->maxs[2], maxs[2]);
6193 // merge this surface's materialflags into the waterplane
6194 p->materialflags |= t->currentmaterialflags;
6195 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6197 // merge this surface's PVS into the waterplane
6198 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6199 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6201 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6207 extern cvar_t r_drawparticles;
6208 extern cvar_t r_drawdecals;
6210 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6213 r_refdef_view_t originalview;
6214 r_refdef_view_t myview;
6215 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;
6216 r_waterstate_waterplane_t *p;
6218 qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6221 originalview = r_refdef.view;
6223 // lowquality hack, temporarily shut down some cvars and restore afterwards
6224 qualityreduction = r_water_lowquality.integer;
6225 if (qualityreduction > 0)
6227 if (qualityreduction >= 1)
6229 old_r_shadows = r_shadows.integer;
6230 old_r_worldrtlight = r_shadow_realtime_world.integer;
6231 old_r_dlight = r_shadow_realtime_dlight.integer;
6232 Cvar_SetValueQuick(&r_shadows, 0);
6233 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6234 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6236 if (qualityreduction >= 2)
6238 old_r_dynamic = r_dynamic.integer;
6239 old_r_particles = r_drawparticles.integer;
6240 old_r_decals = r_drawdecals.integer;
6241 Cvar_SetValueQuick(&r_dynamic, 0);
6242 Cvar_SetValueQuick(&r_drawparticles, 0);
6243 Cvar_SetValueQuick(&r_drawdecals, 0);
6247 // make sure enough textures are allocated
6248 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6250 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6252 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6254 if (!p->texture_refraction)
6255 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6256 if (!p->texture_refraction)
6260 if (r_fb.water.depthtexture == NULL)
6261 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6262 if (p->fbo_refraction == 0)
6263 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6266 else if (p->materialflags & MATERIALFLAG_CAMERA)
6268 if (!p->texture_camera)
6269 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
6270 if (!p->texture_camera)
6274 if (r_fb.water.depthtexture == NULL)
6275 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6276 if (p->fbo_camera == 0)
6277 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6281 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6283 if (!p->texture_reflection)
6284 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6285 if (!p->texture_reflection)
6289 if (r_fb.water.depthtexture == NULL)
6290 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6291 if (p->fbo_reflection == 0)
6292 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6298 r_refdef.view = originalview;
6299 r_refdef.view.showdebug = false;
6300 r_refdef.view.width = r_fb.water.waterwidth;
6301 r_refdef.view.height = r_fb.water.waterheight;
6302 r_refdef.view.useclipplane = true;
6303 myview = r_refdef.view;
6304 r_fb.water.renderingscene = true;
6305 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6307 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6309 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6311 r_refdef.view = myview;
6312 if(r_water_scissormode.integer)
6314 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6315 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6316 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6319 // render reflected scene and copy into texture
6320 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6321 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6322 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6323 r_refdef.view.clipplane = p->plane;
6324 // reverse the cullface settings for this render
6325 r_refdef.view.cullface_front = GL_FRONT;
6326 r_refdef.view.cullface_back = GL_BACK;
6327 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6329 r_refdef.view.usecustompvs = true;
6331 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6333 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6336 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6337 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6338 R_ClearScreen(r_refdef.fogenabled);
6339 if(r_water_scissormode.integer & 2)
6340 R_View_UpdateWithScissor(myscissor);
6343 R_AnimCache_CacheVisibleEntities();
6344 if(r_water_scissormode.integer & 1)
6345 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6346 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6348 if (!p->fbo_reflection)
6349 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6350 r_fb.water.hideplayer = false;
6353 // render the normal view scene and copy into texture
6354 // (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)
6355 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6357 r_refdef.view = myview;
6358 if(r_water_scissormode.integer)
6360 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6361 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6362 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6365 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6367 r_refdef.view.clipplane = p->plane;
6368 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6369 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6371 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6373 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6374 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6375 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6376 R_RenderView_UpdateViewVectors();
6377 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6379 r_refdef.view.usecustompvs = true;
6380 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);
6384 PlaneClassify(&r_refdef.view.clipplane);
6386 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6387 R_ClearScreen(r_refdef.fogenabled);
6388 if(r_water_scissormode.integer & 2)
6389 R_View_UpdateWithScissor(myscissor);
6392 R_AnimCache_CacheVisibleEntities();
6393 if(r_water_scissormode.integer & 1)
6394 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6395 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6397 if (!p->fbo_refraction)
6398 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6399 r_fb.water.hideplayer = false;
6401 else if (p->materialflags & MATERIALFLAG_CAMERA)
6403 r_refdef.view = myview;
6405 r_refdef.view.clipplane = p->plane;
6406 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6407 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6409 r_refdef.view.width = r_fb.water.camerawidth;
6410 r_refdef.view.height = r_fb.water.cameraheight;
6411 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6412 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6413 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6414 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6416 if(p->camera_entity)
6418 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6419 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6422 // note: all of the view is used for displaying... so
6423 // there is no use in scissoring
6425 // reverse the cullface settings for this render
6426 r_refdef.view.cullface_front = GL_FRONT;
6427 r_refdef.view.cullface_back = GL_BACK;
6428 // also reverse the view matrix
6429 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
6430 R_RenderView_UpdateViewVectors();
6431 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6433 r_refdef.view.usecustompvs = true;
6434 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);
6437 // camera needs no clipplane
6438 r_refdef.view.useclipplane = false;
6440 PlaneClassify(&r_refdef.view.clipplane);
6442 r_fb.water.hideplayer = false;
6444 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6445 R_ClearScreen(r_refdef.fogenabled);
6447 R_AnimCache_CacheVisibleEntities();
6448 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6451 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6452 r_fb.water.hideplayer = false;
6456 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6457 r_fb.water.renderingscene = false;
6458 r_refdef.view = originalview;
6459 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6460 if (!r_fb.water.depthtexture)
6461 R_ClearScreen(r_refdef.fogenabled);
6463 R_AnimCache_CacheVisibleEntities();
6466 r_refdef.view = originalview;
6467 r_fb.water.renderingscene = false;
6468 Cvar_SetValueQuick(&r_water, 0);
6469 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6471 // lowquality hack, restore cvars
6472 if (qualityreduction > 0)
6474 if (qualityreduction >= 1)
6476 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6477 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6478 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6480 if (qualityreduction >= 2)
6482 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6483 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6484 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6489 static void R_Bloom_StartFrame(void)
6492 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6493 int viewwidth, viewheight;
6494 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6495 textype_t textype = TEXTYPE_COLORBUFFER;
6497 switch (vid.renderpath)
6499 case RENDERPATH_GL20:
6500 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6501 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6503 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6504 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6507 case RENDERPATH_GL11:
6508 case RENDERPATH_GL13:
6509 case RENDERPATH_GLES1:
6510 return; // don't bother
6511 case RENDERPATH_GLES2:
6512 case RENDERPATH_D3D9:
6513 case RENDERPATH_D3D10:
6514 case RENDERPATH_D3D11:
6515 r_fb.usedepthtextures = false;
6517 case RENDERPATH_SOFT:
6518 r_fb.usedepthtextures = true;
6522 if (r_viewscale_fpsscaling.integer)
6524 double actualframetime;
6525 double targetframetime;
6527 actualframetime = r_refdef.lastdrawscreentime;
6528 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6529 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6530 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6531 if (r_viewscale_fpsscaling_stepsize.value > 0)
6532 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6533 viewscalefpsadjusted += adjust;
6534 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6537 viewscalefpsadjusted = 1.0f;
6539 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6541 switch(vid.renderpath)
6543 case RENDERPATH_GL20:
6544 case RENDERPATH_D3D9:
6545 case RENDERPATH_D3D10:
6546 case RENDERPATH_D3D11:
6547 case RENDERPATH_SOFT:
6548 case RENDERPATH_GLES2:
6550 case RENDERPATH_GL11:
6551 case RENDERPATH_GL13:
6552 case RENDERPATH_GLES1:
6556 // set bloomwidth and bloomheight to the bloom resolution that will be
6557 // used (often less than the screen resolution for faster rendering)
6558 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6559 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6560 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6561 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6562 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6564 // calculate desired texture sizes
6565 if (vid.support.arb_texture_non_power_of_two)
6567 screentexturewidth = vid.width;
6568 screentextureheight = vid.height;
6569 bloomtexturewidth = r_fb.bloomwidth;
6570 bloomtextureheight = r_fb.bloomheight;
6574 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6575 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6576 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6577 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6580 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))
6582 Cvar_SetValueQuick(&r_bloom, 0);
6583 Cvar_SetValueQuick(&r_motionblur, 0);
6584 Cvar_SetValueQuick(&r_damageblur, 0);
6587 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6589 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6591 && r_viewscale.value == 1.0f
6592 && !r_viewscale_fpsscaling.integer)
6593 screentexturewidth = screentextureheight = 0;
6594 if (!r_bloom.integer)
6595 bloomtexturewidth = bloomtextureheight = 0;
6597 // allocate textures as needed
6598 if (r_fb.screentexturewidth != screentexturewidth
6599 || r_fb.screentextureheight != screentextureheight
6600 || r_fb.bloomtexturewidth != bloomtexturewidth
6601 || r_fb.bloomtextureheight != bloomtextureheight
6602 || r_fb.textype != textype
6603 || useviewfbo != (r_fb.fbo != 0))
6605 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6607 if (r_fb.bloomtexture[i])
6608 R_FreeTexture(r_fb.bloomtexture[i]);
6609 r_fb.bloomtexture[i] = NULL;
6611 if (r_fb.bloomfbo[i])
6612 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6613 r_fb.bloomfbo[i] = 0;
6617 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6620 if (r_fb.colortexture)
6621 R_FreeTexture(r_fb.colortexture);
6622 r_fb.colortexture = NULL;
6624 if (r_fb.depthtexture)
6625 R_FreeTexture(r_fb.depthtexture);
6626 r_fb.depthtexture = NULL;
6628 if (r_fb.ghosttexture)
6629 R_FreeTexture(r_fb.ghosttexture);
6630 r_fb.ghosttexture = NULL;
6632 r_fb.screentexturewidth = screentexturewidth;
6633 r_fb.screentextureheight = screentextureheight;
6634 r_fb.bloomtexturewidth = bloomtexturewidth;
6635 r_fb.bloomtextureheight = bloomtextureheight;
6636 r_fb.textype = textype;
6638 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6640 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6641 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);
6642 r_fb.ghosttexture_valid = false;
6643 r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6646 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6647 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6648 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6652 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6654 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6656 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6658 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6663 // bloom texture is a different resolution
6664 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6665 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6666 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6667 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6668 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6670 // set up a texcoord array for the full resolution screen image
6671 // (we have to keep this around to copy back during final render)
6672 r_fb.screentexcoord2f[0] = 0;
6673 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6674 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6675 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6676 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6677 r_fb.screentexcoord2f[5] = 0;
6678 r_fb.screentexcoord2f[6] = 0;
6679 r_fb.screentexcoord2f[7] = 0;
6683 for (i = 1;i < 8;i += 2)
6685 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6689 // set up a texcoord array for the reduced resolution bloom image
6690 // (which will be additive blended over the screen image)
6691 r_fb.bloomtexcoord2f[0] = 0;
6692 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6693 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6694 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6695 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6696 r_fb.bloomtexcoord2f[5] = 0;
6697 r_fb.bloomtexcoord2f[6] = 0;
6698 r_fb.bloomtexcoord2f[7] = 0;
6700 switch(vid.renderpath)
6702 case RENDERPATH_GL11:
6703 case RENDERPATH_GL13:
6704 case RENDERPATH_GL20:
6705 case RENDERPATH_SOFT:
6706 case RENDERPATH_GLES1:
6707 case RENDERPATH_GLES2:
6709 case RENDERPATH_D3D9:
6710 case RENDERPATH_D3D10:
6711 case RENDERPATH_D3D11:
6712 for (i = 0;i < 4;i++)
6714 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6715 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6716 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6717 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6722 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6725 r_refdef.view.clear = true;
6728 static void R_Bloom_MakeTexture(void)
6731 float xoffset, yoffset, r, brighten;
6733 float colorscale = r_bloom_colorscale.value;
6735 r_refdef.stats[r_stat_bloom]++;
6738 // this copy is unnecessary since it happens in R_BlendView already
6741 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6742 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6746 // scale down screen texture to the bloom texture size
6748 r_fb.bloomindex = 0;
6749 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6750 R_SetViewport(&r_fb.bloomviewport);
6751 GL_CullFace(GL_NONE);
6752 GL_DepthTest(false);
6753 GL_BlendFunc(GL_ONE, GL_ZERO);
6754 GL_Color(colorscale, colorscale, colorscale, 1);
6755 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6756 switch(vid.renderpath)
6758 case RENDERPATH_GL11:
6759 case RENDERPATH_GL13:
6760 case RENDERPATH_GL20:
6761 case RENDERPATH_GLES1:
6762 case RENDERPATH_GLES2:
6763 case RENDERPATH_SOFT:
6764 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6766 case RENDERPATH_D3D9:
6767 case RENDERPATH_D3D10:
6768 case RENDERPATH_D3D11:
6769 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6772 // TODO: do boxfilter scale-down in shader?
6773 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6774 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6775 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6777 // we now have a properly scaled bloom image
6778 if (!r_fb.bloomfbo[r_fb.bloomindex])
6780 // copy it into the bloom texture
6781 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6782 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6785 // multiply bloom image by itself as many times as desired
6786 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6788 intex = r_fb.bloomtexture[r_fb.bloomindex];
6789 r_fb.bloomindex ^= 1;
6790 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6792 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6793 if (!r_fb.bloomfbo[r_fb.bloomindex])
6795 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6796 GL_Color(r,r,r,1); // apply fix factor
6801 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6802 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6803 GL_Color(1,1,1,1); // no fix factor supported here
6805 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6806 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6807 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6808 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6810 if (!r_fb.bloomfbo[r_fb.bloomindex])
6812 // copy the darkened image to a texture
6813 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6814 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6818 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6819 brighten = r_bloom_brighten.value;
6820 brighten = sqrt(brighten);
6822 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6824 for (dir = 0;dir < 2;dir++)
6826 intex = r_fb.bloomtexture[r_fb.bloomindex];
6827 r_fb.bloomindex ^= 1;
6828 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6829 // blend on at multiple vertical offsets to achieve a vertical blur
6830 // TODO: do offset blends using GLSL
6831 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6832 GL_BlendFunc(GL_ONE, GL_ZERO);
6833 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6834 for (x = -range;x <= range;x++)
6836 if (!dir){xoffset = 0;yoffset = x;}
6837 else {xoffset = x;yoffset = 0;}
6838 xoffset /= (float)r_fb.bloomtexturewidth;
6839 yoffset /= (float)r_fb.bloomtextureheight;
6840 // compute a texcoord array with the specified x and y offset
6841 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6842 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6843 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6844 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6845 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6846 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6847 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6848 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6849 // this r value looks like a 'dot' particle, fading sharply to
6850 // black at the edges
6851 // (probably not realistic but looks good enough)
6852 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6853 //r = brighten/(range*2+1);
6854 r = brighten / (range * 2 + 1);
6856 r *= (1 - x*x/(float)(range*range));
6857 GL_Color(r, r, r, 1);
6858 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6859 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6860 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6861 GL_BlendFunc(GL_ONE, GL_ONE);
6864 if (!r_fb.bloomfbo[r_fb.bloomindex])
6866 // copy the vertically or horizontally blurred bloom view to a texture
6867 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6868 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6873 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6875 dpuint64 permutation;
6876 float uservecs[4][4];
6878 R_EntityMatrix(&identitymatrix);
6880 switch (vid.renderpath)
6882 case RENDERPATH_GL20:
6883 case RENDERPATH_D3D9:
6884 case RENDERPATH_D3D10:
6885 case RENDERPATH_D3D11:
6886 case RENDERPATH_SOFT:
6887 case RENDERPATH_GLES2:
6889 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6890 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6891 | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6892 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6893 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6895 if (r_fb.colortexture)
6899 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6900 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6903 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6905 // declare variables
6906 float blur_factor, blur_mouseaccel, blur_velocity;
6907 static float blur_average;
6908 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6910 // set a goal for the factoring
6911 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6912 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6913 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6914 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6915 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6916 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6918 // from the goal, pick an averaged value between goal and last value
6919 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6920 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6922 // enforce minimum amount of blur
6923 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6925 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6927 // calculate values into a standard alpha
6928 cl.motionbluralpha = 1 - exp(-
6930 (r_motionblur.value * blur_factor / 80)
6932 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6935 max(0.0001, cl.time - cl.oldtime) // fps independent
6938 // randomization for the blur value to combat persistent ghosting
6939 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6940 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6943 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6944 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6946 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6947 GL_Color(1, 1, 1, cl.motionbluralpha);
6948 switch(vid.renderpath)
6950 case RENDERPATH_GL11:
6951 case RENDERPATH_GL13:
6952 case RENDERPATH_GL20:
6953 case RENDERPATH_GLES1:
6954 case RENDERPATH_GLES2:
6955 case RENDERPATH_SOFT:
6956 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6958 case RENDERPATH_D3D9:
6959 case RENDERPATH_D3D10:
6960 case RENDERPATH_D3D11:
6961 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6964 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6965 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6966 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6969 // updates old view angles for next pass
6970 VectorCopy(cl.viewangles, blur_oldangles);
6972 // copy view into the ghost texture
6973 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6974 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6975 r_fb.ghosttexture_valid = true;
6980 // no r_fb.colortexture means we're rendering to the real fb
6981 // we may still have to do view tint...
6982 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6984 // apply a color tint to the whole view
6985 R_ResetViewRendering2D(0, NULL, NULL);
6986 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6987 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6988 R_SetupShader_Generic_NoTexture(false, true);
6989 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6990 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6992 break; // no screen processing, no bloom, skip it
6995 if (r_fb.bloomtexture[0])
6997 // make the bloom texture
6998 R_Bloom_MakeTexture();
7001 #if _MSC_VER >= 1400
7002 #define sscanf sscanf_s
7004 memset(uservecs, 0, sizeof(uservecs));
7005 if (r_glsl_postprocess_uservec1_enable.integer)
7006 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7007 if (r_glsl_postprocess_uservec2_enable.integer)
7008 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7009 if (r_glsl_postprocess_uservec3_enable.integer)
7010 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7011 if (r_glsl_postprocess_uservec4_enable.integer)
7012 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7014 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
7015 GL_Color(1, 1, 1, 1);
7016 GL_BlendFunc(GL_ONE, GL_ZERO);
7018 switch(vid.renderpath)
7020 case RENDERPATH_GL20:
7021 case RENDERPATH_GLES2:
7022 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7023 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7024 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
7025 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
7026 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
7027 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]);
7028 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7029 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]);
7030 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]);
7031 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]);
7032 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]);
7033 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7034 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7035 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);
7037 case RENDERPATH_D3D9:
7039 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
7040 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7041 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
7042 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
7043 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
7044 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7045 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7046 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7047 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7048 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7049 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7050 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7051 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
7052 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7053 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7056 case RENDERPATH_D3D10:
7057 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7059 case RENDERPATH_D3D11:
7060 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7062 case RENDERPATH_SOFT:
7063 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7064 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7065 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
7066 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
7067 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7068 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7069 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7070 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7071 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7072 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7073 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7074 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
7075 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7076 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7081 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7082 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7084 case RENDERPATH_GL11:
7085 case RENDERPATH_GL13:
7086 case RENDERPATH_GLES1:
7087 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7089 // apply a color tint to the whole view
7090 R_ResetViewRendering2D(0, NULL, NULL);
7091 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7092 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7093 R_SetupShader_Generic_NoTexture(false, true);
7094 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7095 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7101 matrix4x4_t r_waterscrollmatrix;
7103 void R_UpdateFog(void)
7106 if (gamemode == GAME_NEHAHRA)
7108 if (gl_fogenable.integer)
7110 r_refdef.oldgl_fogenable = true;
7111 r_refdef.fog_density = gl_fogdensity.value;
7112 r_refdef.fog_red = gl_fogred.value;
7113 r_refdef.fog_green = gl_foggreen.value;
7114 r_refdef.fog_blue = gl_fogblue.value;
7115 r_refdef.fog_alpha = 1;
7116 r_refdef.fog_start = 0;
7117 r_refdef.fog_end = gl_skyclip.value;
7118 r_refdef.fog_height = 1<<30;
7119 r_refdef.fog_fadedepth = 128;
7121 else if (r_refdef.oldgl_fogenable)
7123 r_refdef.oldgl_fogenable = false;
7124 r_refdef.fog_density = 0;
7125 r_refdef.fog_red = 0;
7126 r_refdef.fog_green = 0;
7127 r_refdef.fog_blue = 0;
7128 r_refdef.fog_alpha = 0;
7129 r_refdef.fog_start = 0;
7130 r_refdef.fog_end = 0;
7131 r_refdef.fog_height = 1<<30;
7132 r_refdef.fog_fadedepth = 128;
7137 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7138 r_refdef.fog_start = max(0, r_refdef.fog_start);
7139 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7141 if (r_refdef.fog_density && r_drawfog.integer)
7143 r_refdef.fogenabled = true;
7144 // this is the point where the fog reaches 0.9986 alpha, which we
7145 // consider a good enough cutoff point for the texture
7146 // (0.9986 * 256 == 255.6)
7147 if (r_fog_exp2.integer)
7148 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7150 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7151 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7152 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7153 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7154 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7155 R_BuildFogHeightTexture();
7156 // fog color was already set
7157 // update the fog texture
7158 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)
7159 R_BuildFogTexture();
7160 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7161 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7164 r_refdef.fogenabled = false;
7167 if (r_refdef.fog_density)
7169 r_refdef.fogcolor[0] = r_refdef.fog_red;
7170 r_refdef.fogcolor[1] = r_refdef.fog_green;
7171 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7173 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7174 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7175 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7176 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7180 VectorCopy(r_refdef.fogcolor, fogvec);
7181 // color.rgb *= ContrastBoost * SceneBrightness;
7182 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7183 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7184 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7185 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7190 void R_UpdateVariables(void)
7194 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7196 r_refdef.farclip = r_farclip_base.value;
7197 if (r_refdef.scene.worldmodel)
7198 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7199 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7201 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7202 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7203 r_refdef.polygonfactor = 0;
7204 r_refdef.polygonoffset = 0;
7205 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7206 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7208 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7209 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7210 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7211 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7212 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7213 if (FAKELIGHT_ENABLED)
7215 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7217 else if (r_refdef.scene.worldmodel)
7219 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7221 if (r_showsurfaces.integer)
7223 r_refdef.scene.rtworld = false;
7224 r_refdef.scene.rtworldshadows = false;
7225 r_refdef.scene.rtdlight = false;
7226 r_refdef.scene.rtdlightshadows = false;
7227 r_refdef.lightmapintensity = 0;
7230 r_gpuskeletal = false;
7231 switch(vid.renderpath)
7233 case RENDERPATH_GL20:
7234 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7235 case RENDERPATH_D3D9:
7236 case RENDERPATH_D3D10:
7237 case RENDERPATH_D3D11:
7238 case RENDERPATH_SOFT:
7239 case RENDERPATH_GLES2:
7240 if(!vid_gammatables_trivial)
7242 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7244 // build GLSL gamma texture
7245 #define RAMPWIDTH 256
7246 unsigned short ramp[RAMPWIDTH * 3];
7247 unsigned char rampbgr[RAMPWIDTH][4];
7250 r_texture_gammaramps_serial = vid_gammatables_serial;
7252 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7253 for(i = 0; i < RAMPWIDTH; ++i)
7255 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7256 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7257 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7260 if (r_texture_gammaramps)
7262 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7266 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7272 // remove GLSL gamma texture
7275 case RENDERPATH_GL11:
7276 case RENDERPATH_GL13:
7277 case RENDERPATH_GLES1:
7282 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7283 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7289 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7290 if( scenetype != r_currentscenetype ) {
7291 // store the old scenetype
7292 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7293 r_currentscenetype = scenetype;
7294 // move in the new scene
7295 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7304 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7306 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7307 if( scenetype == r_currentscenetype ) {
7308 return &r_refdef.scene;
7310 return &r_scenes_store[ scenetype ];
7314 static int R_SortEntities_Compare(const void *ap, const void *bp)
7316 const entity_render_t *a = *(const entity_render_t **)ap;
7317 const entity_render_t *b = *(const entity_render_t **)bp;
7320 if(a->model < b->model)
7322 if(a->model > b->model)
7326 // TODO possibly calculate the REAL skinnum here first using
7328 if(a->skinnum < b->skinnum)
7330 if(a->skinnum > b->skinnum)
7333 // everything we compared is equal
7336 static void R_SortEntities(void)
7338 // below or equal 2 ents, sorting never gains anything
7339 if(r_refdef.scene.numentities <= 2)
7342 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7350 int dpsoftrast_test;
7351 extern cvar_t r_shadow_bouncegrid;
7352 void R_RenderView(void)
7354 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7356 rtexture_t *depthtexture;
7357 rtexture_t *colortexture;
7359 dpsoftrast_test = r_test.integer;
7361 if (r_timereport_active)
7362 R_TimeReport("start");
7363 r_textureframe++; // used only by R_GetCurrentTexture
7364 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7366 if(R_CompileShader_CheckStaticParms())
7369 if (!r_drawentities.integer)
7370 r_refdef.scene.numentities = 0;
7371 else if (r_sortentities.integer)
7374 R_AnimCache_ClearCache();
7376 /* adjust for stereo display */
7377 if(R_Stereo_Active())
7379 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);
7380 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7383 if (r_refdef.view.isoverlay)
7385 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7386 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7387 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7388 R_TimeReport("depthclear");
7390 r_refdef.view.showdebug = false;
7392 r_fb.water.enabled = false;
7393 r_fb.water.numwaterplanes = 0;
7395 R_RenderScene(0, NULL, NULL);
7397 r_refdef.view.matrix = originalmatrix;
7403 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7405 r_refdef.view.matrix = originalmatrix;
7409 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7411 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7412 // in sRGB fallback, behave similar to true sRGB: convert this
7413 // value from linear to sRGB
7414 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7416 R_RenderView_UpdateViewVectors();
7418 R_Shadow_UpdateWorldLightSelection();
7420 R_Bloom_StartFrame();
7422 // apply bloom brightness offset
7423 if(r_fb.bloomtexture[0])
7424 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7426 R_Water_StartFrame();
7428 // now we probably have an fbo to render into
7430 depthtexture = r_fb.depthtexture;
7431 colortexture = r_fb.colortexture;
7434 if (r_timereport_active)
7435 R_TimeReport("viewsetup");
7437 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7439 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7441 R_ClearScreen(r_refdef.fogenabled);
7442 if (r_timereport_active)
7443 R_TimeReport("viewclear");
7445 r_refdef.view.clear = true;
7447 r_refdef.view.showdebug = true;
7450 if (r_timereport_active)
7451 R_TimeReport("visibility");
7453 R_AnimCache_CacheVisibleEntities();
7454 if (r_timereport_active)
7455 R_TimeReport("animcache");
7457 R_Shadow_UpdateBounceGridTexture();
7458 if (r_timereport_active && r_shadow_bouncegrid.integer)
7459 R_TimeReport("bouncegrid");
7461 r_fb.water.numwaterplanes = 0;
7462 if (r_fb.water.enabled)
7463 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7465 R_RenderScene(fbo, depthtexture, colortexture);
7466 r_fb.water.numwaterplanes = 0;
7468 R_BlendView(fbo, depthtexture, colortexture);
7469 if (r_timereport_active)
7470 R_TimeReport("blendview");
7472 GL_Scissor(0, 0, vid.width, vid.height);
7473 GL_ScissorTest(false);
7475 r_refdef.view.matrix = originalmatrix;
7480 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7482 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7484 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7485 if (r_timereport_active)
7486 R_TimeReport("waterworld");
7489 // don't let sound skip if going slow
7490 if (r_refdef.scene.extraupdate)
7493 R_DrawModelsAddWaterPlanes();
7494 if (r_timereport_active)
7495 R_TimeReport("watermodels");
7497 if (r_fb.water.numwaterplanes)
7499 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7500 if (r_timereport_active)
7501 R_TimeReport("waterscenes");
7505 extern cvar_t cl_locs_show;
7506 static void R_DrawLocs(void);
7507 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7508 static void R_DrawModelDecals(void);
7509 extern cvar_t cl_decals_newsystem;
7510 extern qboolean r_shadow_usingdeferredprepass;
7511 extern int r_shadow_shadowmapatlas_modelshadows_size;
7512 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7514 qboolean shadowmapping = false;
7516 if (r_timereport_active)
7517 R_TimeReport("beginscene");
7519 r_refdef.stats[r_stat_renders]++;
7523 // don't let sound skip if going slow
7524 if (r_refdef.scene.extraupdate)
7527 R_MeshQueue_BeginScene();
7531 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);
7533 if (r_timereport_active)
7534 R_TimeReport("skystartframe");
7536 if (cl.csqc_vidvars.drawworld)
7538 // don't let sound skip if going slow
7539 if (r_refdef.scene.extraupdate)
7542 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7544 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7545 if (r_timereport_active)
7546 R_TimeReport("worldsky");
7549 if (R_DrawBrushModelsSky() && r_timereport_active)
7550 R_TimeReport("bmodelsky");
7552 if (skyrendermasked && skyrenderlater)
7554 // we have to force off the water clipping plane while rendering sky
7555 R_SetupView(false, fbo, depthtexture, colortexture);
7557 R_SetupView(true, fbo, depthtexture, colortexture);
7558 if (r_timereport_active)
7559 R_TimeReport("sky");
7563 R_Shadow_PrepareModelShadows();
7564 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7565 if (r_timereport_active)
7566 R_TimeReport("preparelights");
7568 // render all the shadowmaps that will be used for this view
7569 shadowmapping = R_Shadow_ShadowMappingEnabled();
7570 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7572 R_Shadow_DrawShadowMaps();
7573 if (r_timereport_active)
7574 R_TimeReport("shadowmaps");
7577 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7578 if (r_shadow_usingdeferredprepass)
7579 R_Shadow_DrawPrepass();
7581 // now we begin the forward pass of the view render
7582 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7584 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7585 if (r_timereport_active)
7586 R_TimeReport("worlddepth");
7588 if (r_depthfirst.integer >= 2)
7590 R_DrawModelsDepth();
7591 if (r_timereport_active)
7592 R_TimeReport("modeldepth");
7595 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7597 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7598 if (r_timereport_active)
7599 R_TimeReport("world");
7602 // don't let sound skip if going slow
7603 if (r_refdef.scene.extraupdate)
7607 if (r_timereport_active)
7608 R_TimeReport("models");
7610 // don't let sound skip if going slow
7611 if (r_refdef.scene.extraupdate)
7614 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7616 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7617 R_Shadow_DrawModelShadows();
7618 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7619 // don't let sound skip if going slow
7620 if (r_refdef.scene.extraupdate)
7624 if (!r_shadow_usingdeferredprepass)
7626 R_Shadow_DrawLights();
7627 if (r_timereport_active)
7628 R_TimeReport("rtlights");
7631 // don't let sound skip if going slow
7632 if (r_refdef.scene.extraupdate)
7635 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7637 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7638 R_Shadow_DrawModelShadows();
7639 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7640 // don't let sound skip if going slow
7641 if (r_refdef.scene.extraupdate)
7645 if (cl.csqc_vidvars.drawworld)
7647 if (cl_decals_newsystem.integer)
7649 R_DrawModelDecals();
7650 if (r_timereport_active)
7651 R_TimeReport("modeldecals");
7656 if (r_timereport_active)
7657 R_TimeReport("decals");
7661 if (r_timereport_active)
7662 R_TimeReport("particles");
7665 if (r_timereport_active)
7666 R_TimeReport("explosions");
7670 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7672 if (r_refdef.view.showdebug)
7674 if (cl_locs_show.integer)
7677 if (r_timereport_active)
7678 R_TimeReport("showlocs");
7681 if (r_drawportals.integer)
7684 if (r_timereport_active)
7685 R_TimeReport("portals");
7688 if (r_showbboxes_client.value > 0)
7690 R_DrawEntityBBoxes(CLVM_prog);
7691 if (r_timereport_active)
7692 R_TimeReport("clbboxes");
7694 if (r_showbboxes.value > 0)
7696 R_DrawEntityBBoxes(SVVM_prog);
7697 if (r_timereport_active)
7698 R_TimeReport("svbboxes");
7702 if (r_transparent.integer)
7704 R_MeshQueue_RenderTransparent();
7705 if (r_timereport_active)
7706 R_TimeReport("drawtrans");
7709 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))
7711 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7712 if (r_timereport_active)
7713 R_TimeReport("worlddebug");
7714 R_DrawModelsDebug();
7715 if (r_timereport_active)
7716 R_TimeReport("modeldebug");
7719 if (cl.csqc_vidvars.drawworld)
7721 R_Shadow_DrawCoronas();
7722 if (r_timereport_active)
7723 R_TimeReport("coronas");
7728 GL_DepthTest(false);
7729 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7730 GL_Color(1, 1, 1, 1);
7731 qglBegin(GL_POLYGON);
7732 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7733 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7734 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7735 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7737 qglBegin(GL_POLYGON);
7738 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]);
7739 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]);
7740 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]);
7741 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]);
7743 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7747 // don't let sound skip if going slow
7748 if (r_refdef.scene.extraupdate)
7752 static const unsigned short bboxelements[36] =
7762 #define BBOXEDGES 13
7763 static const float bboxedges[BBOXEDGES][6] =
7766 { 0, 0, 0, 1, 1, 1 },
7768 { 0, 0, 0, 0, 1, 0 },
7769 { 0, 0, 0, 1, 0, 0 },
7770 { 0, 1, 0, 1, 1, 0 },
7771 { 1, 0, 0, 1, 1, 0 },
7773 { 0, 0, 1, 0, 1, 1 },
7774 { 0, 0, 1, 1, 0, 1 },
7775 { 0, 1, 1, 1, 1, 1 },
7776 { 1, 0, 1, 1, 1, 1 },
7778 { 0, 0, 0, 0, 0, 1 },
7779 { 1, 0, 0, 1, 0, 1 },
7780 { 0, 1, 0, 0, 1, 1 },
7781 { 1, 1, 0, 1, 1, 1 },
7784 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7786 int numvertices = BBOXEDGES * 8;
7787 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7788 int numtriangles = BBOXEDGES * 12;
7789 unsigned short elements[BBOXEDGES * 36];
7791 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7793 RSurf_ActiveWorldEntity();
7795 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7796 GL_DepthMask(false);
7797 GL_DepthRange(0, 1);
7798 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7800 for (edge = 0; edge < BBOXEDGES; edge++)
7802 for (i = 0; i < 3; i++)
7804 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7805 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7807 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7808 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7809 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7810 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7811 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7812 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7813 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7814 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7815 for (i = 0; i < 36; i++)
7816 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7818 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7819 if (r_refdef.fogenabled)
7821 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7823 f1 = RSurf_FogVertex(v);
7825 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7826 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7827 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7830 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7831 R_Mesh_ResetTextureState();
7832 R_SetupShader_Generic_NoTexture(false, false);
7833 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7836 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7838 // hacky overloading of the parameters
7839 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7842 prvm_edict_t *edict;
7844 GL_CullFace(GL_NONE);
7845 R_SetupShader_Generic_NoTexture(false, false);
7847 for (i = 0;i < numsurfaces;i++)
7849 edict = PRVM_EDICT_NUM(surfacelist[i]);
7850 switch ((int)PRVM_serveredictfloat(edict, solid))
7852 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7853 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7854 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7855 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7856 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7857 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7858 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7860 if (prog == CLVM_prog)
7861 color[3] *= r_showbboxes_client.value;
7863 color[3] *= r_showbboxes.value;
7864 color[3] = bound(0, color[3], 1);
7865 GL_DepthTest(!r_showdisabledepthtest.integer);
7866 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7870 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7873 prvm_edict_t *edict;
7879 for (i = 0; i < prog->num_edicts; i++)
7881 edict = PRVM_EDICT_NUM(i);
7882 if (edict->priv.server->free)
7884 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7885 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7887 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7889 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7890 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7894 static const int nomodelelement3i[24] =
7906 static const unsigned short nomodelelement3s[24] =
7918 static const float nomodelvertex3f[6*3] =
7928 static const float nomodelcolor4f[6*4] =
7930 0.0f, 0.0f, 0.5f, 1.0f,
7931 0.0f, 0.0f, 0.5f, 1.0f,
7932 0.0f, 0.5f, 0.0f, 1.0f,
7933 0.0f, 0.5f, 0.0f, 1.0f,
7934 0.5f, 0.0f, 0.0f, 1.0f,
7935 0.5f, 0.0f, 0.0f, 1.0f
7938 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7944 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);
7946 // this is only called once per entity so numsurfaces is always 1, and
7947 // surfacelist is always {0}, so this code does not handle batches
7949 if (rsurface.ent_flags & RENDER_ADDITIVE)
7951 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7952 GL_DepthMask(false);
7954 else if (rsurface.colormod[3] < 1)
7956 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7957 GL_DepthMask(false);
7961 GL_BlendFunc(GL_ONE, GL_ZERO);
7964 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7965 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7966 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7967 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7968 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7969 for (i = 0, c = color4f;i < 6;i++, c += 4)
7971 c[0] *= rsurface.colormod[0];
7972 c[1] *= rsurface.colormod[1];
7973 c[2] *= rsurface.colormod[2];
7974 c[3] *= rsurface.colormod[3];
7976 if (r_refdef.fogenabled)
7978 for (i = 0, c = color4f;i < 6;i++, c += 4)
7980 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7982 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7983 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7984 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7987 // R_Mesh_ResetTextureState();
7988 R_SetupShader_Generic_NoTexture(false, false);
7989 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7990 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7993 void R_DrawNoModel(entity_render_t *ent)
7996 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7997 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7998 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8000 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8003 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
8005 vec3_t right1, right2, diff, normal;
8007 VectorSubtract (org2, org1, normal);
8009 // calculate 'right' vector for start
8010 VectorSubtract (r_refdef.view.origin, org1, diff);
8011 CrossProduct (normal, diff, right1);
8012 VectorNormalize (right1);
8014 // calculate 'right' vector for end
8015 VectorSubtract (r_refdef.view.origin, org2, diff);
8016 CrossProduct (normal, diff, right2);
8017 VectorNormalize (right2);
8019 vert[ 0] = org1[0] + width * right1[0];
8020 vert[ 1] = org1[1] + width * right1[1];
8021 vert[ 2] = org1[2] + width * right1[2];
8022 vert[ 3] = org1[0] - width * right1[0];
8023 vert[ 4] = org1[1] - width * right1[1];
8024 vert[ 5] = org1[2] - width * right1[2];
8025 vert[ 6] = org2[0] - width * right2[0];
8026 vert[ 7] = org2[1] - width * right2[1];
8027 vert[ 8] = org2[2] - width * right2[2];
8028 vert[ 9] = org2[0] + width * right2[0];
8029 vert[10] = org2[1] + width * right2[1];
8030 vert[11] = org2[2] + width * right2[2];
8033 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)
8035 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8036 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8037 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8038 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8039 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8040 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8041 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8042 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8043 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8044 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8045 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8046 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8049 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8054 VectorSet(v, x, y, z);
8055 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8056 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8058 if (i == mesh->numvertices)
8060 if (mesh->numvertices < mesh->maxvertices)
8062 VectorCopy(v, vertex3f);
8063 mesh->numvertices++;
8065 return mesh->numvertices;
8071 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8075 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8076 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8077 e = mesh->element3i + mesh->numtriangles * 3;
8078 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8080 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8081 if (mesh->numtriangles < mesh->maxtriangles)
8086 mesh->numtriangles++;
8088 element[1] = element[2];
8092 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8096 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8097 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8098 e = mesh->element3i + mesh->numtriangles * 3;
8099 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8101 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8102 if (mesh->numtriangles < mesh->maxtriangles)
8107 mesh->numtriangles++;
8109 element[1] = element[2];
8113 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8114 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8116 int planenum, planenum2;
8119 mplane_t *plane, *plane2;
8121 double temppoints[2][256*3];
8122 // figure out how large a bounding box we need to properly compute this brush
8124 for (w = 0;w < numplanes;w++)
8125 maxdist = max(maxdist, fabs(planes[w].dist));
8126 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8127 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8128 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8132 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8133 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8135 if (planenum2 == planenum)
8137 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);
8140 if (tempnumpoints < 3)
8142 // generate elements forming a triangle fan for this polygon
8143 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8147 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)
8149 texturelayer_t *layer;
8150 layer = t->currentlayers + t->currentnumlayers++;
8152 layer->depthmask = depthmask;
8153 layer->blendfunc1 = blendfunc1;
8154 layer->blendfunc2 = blendfunc2;
8155 layer->texture = texture;
8156 layer->texmatrix = *matrix;
8157 layer->color[0] = r;
8158 layer->color[1] = g;
8159 layer->color[2] = b;
8160 layer->color[3] = a;
8163 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8165 if(parms[0] == 0 && parms[1] == 0)
8167 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8168 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8173 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8176 index = parms[2] + rsurface.shadertime * parms[3];
8177 index -= floor(index);
8178 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8181 case Q3WAVEFUNC_NONE:
8182 case Q3WAVEFUNC_NOISE:
8183 case Q3WAVEFUNC_COUNT:
8186 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8187 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8188 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8189 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8190 case Q3WAVEFUNC_TRIANGLE:
8192 f = index - floor(index);
8205 f = parms[0] + parms[1] * f;
8206 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8207 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8211 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8218 matrix4x4_t matrix, temp;
8219 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8220 // it's better to have one huge fixup every 9 hours than gradual
8221 // degradation over time which looks consistently bad after many hours.
8223 // tcmod scroll in particular suffers from this degradation which can't be
8224 // effectively worked around even with floor() tricks because we don't
8225 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8226 // a workaround involving floor() would be incorrect anyway...
8227 shadertime = rsurface.shadertime;
8228 if (shadertime >= 32768.0f)
8229 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8230 switch(tcmod->tcmod)
8234 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8235 matrix = r_waterscrollmatrix;
8237 matrix = identitymatrix;
8239 case Q3TCMOD_ENTITYTRANSLATE:
8240 // this is used in Q3 to allow the gamecode to control texcoord
8241 // scrolling on the entity, which is not supported in darkplaces yet.
8242 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8244 case Q3TCMOD_ROTATE:
8245 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8246 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8247 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8250 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8252 case Q3TCMOD_SCROLL:
8253 // this particular tcmod is a "bug for bug" compatible one with regards to
8254 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8255 // specifically did the wrapping and so we must mimic that...
8256 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8257 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8258 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8260 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8261 w = (int) tcmod->parms[0];
8262 h = (int) tcmod->parms[1];
8263 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8265 idx = (int) floor(f * w * h);
8266 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8268 case Q3TCMOD_STRETCH:
8269 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8270 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8272 case Q3TCMOD_TRANSFORM:
8273 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8274 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8275 VectorSet(tcmat + 6, 0 , 0 , 1);
8276 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8277 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8279 case Q3TCMOD_TURBULENT:
8280 // this is handled in the RSurf_PrepareVertices function
8281 matrix = identitymatrix;
8285 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8288 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8290 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8291 char name[MAX_QPATH];
8292 skinframe_t *skinframe;
8293 unsigned char pixels[296*194];
8294 strlcpy(cache->name, skinname, sizeof(cache->name));
8295 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8296 if (developer_loading.integer)
8297 Con_Printf("loading %s\n", name);
8298 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8299 if (!skinframe || !skinframe->base)
8302 fs_offset_t filesize;
8304 f = FS_LoadFile(name, tempmempool, true, &filesize);
8307 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8308 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8312 cache->skinframe = skinframe;
8315 texture_t *R_GetCurrentTexture(texture_t *t)
8318 const entity_render_t *ent = rsurface.entity;
8319 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8320 q3shaderinfo_layer_tcmod_t *tcmod;
8322 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8323 return t->currentframe;
8324 t->update_lastrenderframe = r_textureframe;
8325 t->update_lastrenderentity = (void *)ent;
8327 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8328 t->camera_entity = ent->entitynumber;
8330 t->camera_entity = 0;
8332 // switch to an alternate material if this is a q1bsp animated material
8334 texture_t *texture = t;
8335 int s = rsurface.ent_skinnum;
8336 if ((unsigned int)s >= (unsigned int)model->numskins)
8338 if (model->skinscenes)
8340 if (model->skinscenes[s].framecount > 1)
8341 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8343 s = model->skinscenes[s].firstframe;
8346 t = t + s * model->num_surfaces;
8349 // use an alternate animation if the entity's frame is not 0,
8350 // and only if the texture has an alternate animation
8351 if (t->animated == 2) // q2bsp
8352 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8353 else if (rsurface.ent_alttextures && t->anim_total[1])
8354 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8356 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8358 texture->currentframe = t;
8361 // update currentskinframe to be a qw skin or animation frame
8362 if (rsurface.ent_qwskin >= 0)
8364 i = rsurface.ent_qwskin;
8365 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8367 r_qwskincache_size = cl.maxclients;
8369 Mem_Free(r_qwskincache);
8370 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8372 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8373 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8374 t->currentskinframe = r_qwskincache[i].skinframe;
8375 if (t->materialshaderpass && t->currentskinframe == NULL)
8376 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8378 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8379 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8380 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8381 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8383 t->currentmaterialflags = t->basematerialflags;
8384 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8385 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8386 t->currentalpha *= r_wateralpha.value;
8387 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8388 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8389 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8390 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8391 if (!(rsurface.ent_flags & RENDER_LIGHT))
8392 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8393 else if (FAKELIGHT_ENABLED)
8395 // no modellight if using fakelight for the map
8397 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8399 // pick a model lighting mode
8400 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8401 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8403 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8405 if (rsurface.ent_flags & RENDER_ADDITIVE)
8406 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8407 else if (t->currentalpha < 1)
8408 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8409 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8410 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8411 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8412 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8413 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8414 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8415 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8416 if (t->backgroundshaderpass)
8417 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8418 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8420 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8421 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8424 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8425 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8427 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8428 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8430 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8431 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8433 // there is no tcmod
8434 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8436 t->currenttexmatrix = r_waterscrollmatrix;
8437 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8439 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8441 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8442 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8445 if (t->materialshaderpass)
8446 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8447 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8449 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8450 if (t->currentskinframe->qpixels)
8451 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8452 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8453 if (!t->basetexture)
8454 t->basetexture = r_texture_notexture;
8455 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8456 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8457 t->nmaptexture = t->currentskinframe->nmap;
8458 if (!t->nmaptexture)
8459 t->nmaptexture = r_texture_blanknormalmap;
8460 t->glosstexture = r_texture_black;
8461 t->glowtexture = t->currentskinframe->glow;
8462 t->fogtexture = t->currentskinframe->fog;
8463 t->reflectmasktexture = t->currentskinframe->reflect;
8464 if (t->backgroundshaderpass)
8466 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8467 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8468 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8469 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8470 t->backgroundglosstexture = r_texture_black;
8471 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8472 if (!t->backgroundnmaptexture)
8473 t->backgroundnmaptexture = r_texture_blanknormalmap;
8474 // make sure that if glow is going to be used, both textures are not NULL
8475 if (!t->backgroundglowtexture && t->glowtexture)
8476 t->backgroundglowtexture = r_texture_black;
8477 if (!t->glowtexture && t->backgroundglowtexture)
8478 t->glowtexture = r_texture_black;
8482 t->backgroundbasetexture = r_texture_white;
8483 t->backgroundnmaptexture = r_texture_blanknormalmap;
8484 t->backgroundglosstexture = r_texture_black;
8485 t->backgroundglowtexture = NULL;
8487 t->specularpower = r_shadow_glossexponent.value;
8488 // TODO: store reference values for these in the texture?
8489 t->specularscale = 0;
8490 if (r_shadow_gloss.integer > 0)
8492 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8494 if (r_shadow_glossintensity.value > 0)
8496 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8497 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8498 t->specularscale = r_shadow_glossintensity.value;
8501 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8503 t->glosstexture = r_texture_white;
8504 t->backgroundglosstexture = r_texture_white;
8505 t->specularscale = r_shadow_gloss2intensity.value;
8506 t->specularpower = r_shadow_gloss2exponent.value;
8509 t->specularscale *= t->specularscalemod;
8510 t->specularpower *= t->specularpowermod;
8511 t->rtlightambient = 0;
8513 // lightmaps mode looks bad with dlights using actual texturing, so turn
8514 // off the colormap and glossmap, but leave the normalmap on as it still
8515 // accurately represents the shading involved
8516 if (gl_lightmaps.integer)
8518 t->basetexture = r_texture_grey128;
8519 t->pantstexture = r_texture_black;
8520 t->shirttexture = r_texture_black;
8521 if (gl_lightmaps.integer < 2)
8522 t->nmaptexture = r_texture_blanknormalmap;
8523 t->glosstexture = r_texture_black;
8524 t->glowtexture = NULL;
8525 t->fogtexture = NULL;
8526 t->reflectmasktexture = NULL;
8527 t->backgroundbasetexture = NULL;
8528 if (gl_lightmaps.integer < 2)
8529 t->backgroundnmaptexture = r_texture_blanknormalmap;
8530 t->backgroundglosstexture = r_texture_black;
8531 t->backgroundglowtexture = NULL;
8532 t->specularscale = 0;
8533 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8536 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8537 VectorClear(t->dlightcolor);
8538 t->currentnumlayers = 0;
8539 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8541 int blendfunc1, blendfunc2;
8543 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8545 blendfunc1 = GL_SRC_ALPHA;
8546 blendfunc2 = GL_ONE;
8548 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8550 blendfunc1 = GL_SRC_ALPHA;
8551 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8553 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8555 blendfunc1 = t->customblendfunc[0];
8556 blendfunc2 = t->customblendfunc[1];
8560 blendfunc1 = GL_ONE;
8561 blendfunc2 = GL_ZERO;
8563 // don't colormod evilblend textures
8564 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8565 VectorSet(t->lightmapcolor, 1, 1, 1);
8566 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8567 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8569 // fullbright is not affected by r_refdef.lightmapintensity
8570 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8571 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8572 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8573 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8574 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8578 vec3_t ambientcolor;
8580 // set the color tint used for lights affecting this surface
8581 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8583 // q3bsp has no lightmap updates, so the lightstylevalue that
8584 // would normally be baked into the lightmap must be
8585 // applied to the color
8586 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8587 if (model->type == mod_brushq3)
8588 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8589 colorscale *= r_refdef.lightmapintensity;
8590 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8591 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8592 // basic lit geometry
8593 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8594 // add pants/shirt if needed
8595 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8596 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8597 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8598 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8599 // now add ambient passes if needed
8600 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8602 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8603 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8604 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8605 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8606 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8609 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8610 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8611 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8613 // if this is opaque use alpha blend which will darken the earlier
8616 // if this is an alpha blended material, all the earlier passes
8617 // were darkened by fog already, so we only need to add the fog
8618 // color ontop through the fog mask texture
8620 // if this is an additive blended material, all the earlier passes
8621 // were darkened by fog already, and we should not add fog color
8622 // (because the background was not darkened, there is no fog color
8623 // that was lost behind it).
8624 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8631 rsurfacestate_t rsurface;
8633 void RSurf_ActiveWorldEntity(void)
8635 dp_model_t *model = r_refdef.scene.worldmodel;
8636 //if (rsurface.entity == r_refdef.scene.worldentity)
8638 rsurface.entity = r_refdef.scene.worldentity;
8639 rsurface.skeleton = NULL;
8640 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8641 rsurface.ent_skinnum = 0;
8642 rsurface.ent_qwskin = -1;
8643 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8644 rsurface.shadertime = r_refdef.scene.time;
8645 rsurface.matrix = identitymatrix;
8646 rsurface.inversematrix = identitymatrix;
8647 rsurface.matrixscale = 1;
8648 rsurface.inversematrixscale = 1;
8649 R_EntityMatrix(&identitymatrix);
8650 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8651 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8652 rsurface.fograngerecip = r_refdef.fograngerecip;
8653 rsurface.fogheightfade = r_refdef.fogheightfade;
8654 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8655 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8656 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8658 R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir);
8659 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8663 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8664 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8665 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8667 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8668 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8669 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8670 rsurface.colormod[3] = 1;
8671 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8672 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8673 rsurface.frameblend[0].lerp = 1;
8674 rsurface.ent_alttextures = false;
8675 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8676 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8677 rsurface.entityskeletaltransform3x4 = NULL;
8678 rsurface.entityskeletaltransform3x4buffer = NULL;
8679 rsurface.entityskeletaltransform3x4offset = 0;
8680 rsurface.entityskeletaltransform3x4size = 0;;
8681 rsurface.entityskeletalnumtransforms = 0;
8682 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8683 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8684 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8685 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8686 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8687 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8688 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8689 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8690 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8691 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8692 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8693 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8694 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8695 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8696 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8697 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8698 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8699 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8700 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8701 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8702 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8703 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8704 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8705 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8706 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8707 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8708 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8709 rsurface.modelelement3i = model->surfmesh.data_element3i;
8710 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8711 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8712 rsurface.modelelement3s = model->surfmesh.data_element3s;
8713 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8714 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8715 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8716 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8717 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8718 rsurface.modelsurfaces = model->data_surfaces;
8719 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8720 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8721 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8722 rsurface.modelgeneratedvertex = false;
8723 rsurface.batchgeneratedvertex = false;
8724 rsurface.batchfirstvertex = 0;
8725 rsurface.batchnumvertices = 0;
8726 rsurface.batchfirsttriangle = 0;
8727 rsurface.batchnumtriangles = 0;
8728 rsurface.batchvertex3f = NULL;
8729 rsurface.batchvertex3f_vertexbuffer = NULL;
8730 rsurface.batchvertex3f_bufferoffset = 0;
8731 rsurface.batchsvector3f = NULL;
8732 rsurface.batchsvector3f_vertexbuffer = NULL;
8733 rsurface.batchsvector3f_bufferoffset = 0;
8734 rsurface.batchtvector3f = NULL;
8735 rsurface.batchtvector3f_vertexbuffer = NULL;
8736 rsurface.batchtvector3f_bufferoffset = 0;
8737 rsurface.batchnormal3f = NULL;
8738 rsurface.batchnormal3f_vertexbuffer = NULL;
8739 rsurface.batchnormal3f_bufferoffset = 0;
8740 rsurface.batchlightmapcolor4f = NULL;
8741 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8742 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8743 rsurface.batchtexcoordtexture2f = NULL;
8744 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8745 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8746 rsurface.batchtexcoordlightmap2f = NULL;
8747 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8748 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8749 rsurface.batchskeletalindex4ub = NULL;
8750 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8751 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8752 rsurface.batchskeletalweight4ub = NULL;
8753 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8754 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8755 rsurface.batchvertexmesh = NULL;
8756 rsurface.batchvertexmesh_vertexbuffer = NULL;
8757 rsurface.batchvertexmesh_bufferoffset = 0;
8758 rsurface.batchelement3i = NULL;
8759 rsurface.batchelement3i_indexbuffer = NULL;
8760 rsurface.batchelement3i_bufferoffset = 0;
8761 rsurface.batchelement3s = NULL;
8762 rsurface.batchelement3s_indexbuffer = NULL;
8763 rsurface.batchelement3s_bufferoffset = 0;
8764 rsurface.passcolor4f = NULL;
8765 rsurface.passcolor4f_vertexbuffer = NULL;
8766 rsurface.passcolor4f_bufferoffset = 0;
8767 rsurface.forcecurrenttextureupdate = false;
8770 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8772 dp_model_t *model = ent->model;
8773 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8775 rsurface.entity = (entity_render_t *)ent;
8776 rsurface.skeleton = ent->skeleton;
8777 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8778 rsurface.ent_skinnum = ent->skinnum;
8779 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;
8780 rsurface.ent_flags = ent->flags;
8781 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8783 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8785 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8786 rsurface.matrix = ent->matrix;
8787 rsurface.inversematrix = ent->inversematrix;
8788 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8789 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8790 R_EntityMatrix(&rsurface.matrix);
8791 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8792 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8793 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8794 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8795 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8796 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8797 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8798 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8799 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8800 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8801 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8802 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8803 rsurface.colormod[3] = ent->alpha;
8804 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8805 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8806 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8807 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8808 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8809 if (ent->model->brush.submodel && !prepass)
8811 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8812 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8814 // if the animcache code decided it should use the shader path, skip the deform step
8815 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8816 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8817 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8818 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8819 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8820 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8822 if (ent->animcache_vertex3f)
8824 r_refdef.stats[r_stat_batch_entitycache_count]++;
8825 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8826 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8827 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8828 rsurface.modelvertex3f = ent->animcache_vertex3f;
8829 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8830 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8831 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8832 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8833 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8834 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8835 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8836 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8837 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8838 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8839 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8840 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8841 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8842 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8844 else if (wanttangents)
8846 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8847 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8848 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8849 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8850 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8851 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8852 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8853 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8854 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8855 rsurface.modelvertexmesh = NULL;
8856 rsurface.modelvertexmesh_vertexbuffer = NULL;
8857 rsurface.modelvertexmesh_bufferoffset = 0;
8858 rsurface.modelvertex3f_vertexbuffer = NULL;
8859 rsurface.modelvertex3f_bufferoffset = 0;
8860 rsurface.modelvertex3f_vertexbuffer = 0;
8861 rsurface.modelvertex3f_bufferoffset = 0;
8862 rsurface.modelsvector3f_vertexbuffer = 0;
8863 rsurface.modelsvector3f_bufferoffset = 0;
8864 rsurface.modeltvector3f_vertexbuffer = 0;
8865 rsurface.modeltvector3f_bufferoffset = 0;
8866 rsurface.modelnormal3f_vertexbuffer = 0;
8867 rsurface.modelnormal3f_bufferoffset = 0;
8869 else if (wantnormals)
8871 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8872 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8873 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8874 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8875 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8876 rsurface.modelsvector3f = NULL;
8877 rsurface.modeltvector3f = NULL;
8878 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8879 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8880 rsurface.modelvertexmesh = NULL;
8881 rsurface.modelvertexmesh_vertexbuffer = NULL;
8882 rsurface.modelvertexmesh_bufferoffset = 0;
8883 rsurface.modelvertex3f_vertexbuffer = NULL;
8884 rsurface.modelvertex3f_bufferoffset = 0;
8885 rsurface.modelvertex3f_vertexbuffer = 0;
8886 rsurface.modelvertex3f_bufferoffset = 0;
8887 rsurface.modelsvector3f_vertexbuffer = 0;
8888 rsurface.modelsvector3f_bufferoffset = 0;
8889 rsurface.modeltvector3f_vertexbuffer = 0;
8890 rsurface.modeltvector3f_bufferoffset = 0;
8891 rsurface.modelnormal3f_vertexbuffer = 0;
8892 rsurface.modelnormal3f_bufferoffset = 0;
8896 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8897 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8898 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8899 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8900 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8901 rsurface.modelsvector3f = NULL;
8902 rsurface.modeltvector3f = NULL;
8903 rsurface.modelnormal3f = NULL;
8904 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8905 rsurface.modelvertexmesh = NULL;
8906 rsurface.modelvertexmesh_vertexbuffer = NULL;
8907 rsurface.modelvertexmesh_bufferoffset = 0;
8908 rsurface.modelvertex3f_vertexbuffer = NULL;
8909 rsurface.modelvertex3f_bufferoffset = 0;
8910 rsurface.modelvertex3f_vertexbuffer = 0;
8911 rsurface.modelvertex3f_bufferoffset = 0;
8912 rsurface.modelsvector3f_vertexbuffer = 0;
8913 rsurface.modelsvector3f_bufferoffset = 0;
8914 rsurface.modeltvector3f_vertexbuffer = 0;
8915 rsurface.modeltvector3f_bufferoffset = 0;
8916 rsurface.modelnormal3f_vertexbuffer = 0;
8917 rsurface.modelnormal3f_bufferoffset = 0;
8919 rsurface.modelgeneratedvertex = true;
8923 if (rsurface.entityskeletaltransform3x4)
8925 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8926 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8927 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8928 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8932 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8933 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8934 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8935 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8937 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8938 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8939 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8940 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8941 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8942 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8943 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8944 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8945 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8946 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8947 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8948 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8949 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8950 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8951 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8952 rsurface.modelgeneratedvertex = false;
8954 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8955 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8956 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8957 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8958 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8959 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8960 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8961 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8962 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8963 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8964 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8965 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8966 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8967 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8968 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8969 rsurface.modelelement3i = model->surfmesh.data_element3i;
8970 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8971 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8972 rsurface.modelelement3s = model->surfmesh.data_element3s;
8973 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8974 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8975 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8976 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8977 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8978 rsurface.modelsurfaces = model->data_surfaces;
8979 rsurface.batchgeneratedvertex = false;
8980 rsurface.batchfirstvertex = 0;
8981 rsurface.batchnumvertices = 0;
8982 rsurface.batchfirsttriangle = 0;
8983 rsurface.batchnumtriangles = 0;
8984 rsurface.batchvertex3f = NULL;
8985 rsurface.batchvertex3f_vertexbuffer = NULL;
8986 rsurface.batchvertex3f_bufferoffset = 0;
8987 rsurface.batchsvector3f = NULL;
8988 rsurface.batchsvector3f_vertexbuffer = NULL;
8989 rsurface.batchsvector3f_bufferoffset = 0;
8990 rsurface.batchtvector3f = NULL;
8991 rsurface.batchtvector3f_vertexbuffer = NULL;
8992 rsurface.batchtvector3f_bufferoffset = 0;
8993 rsurface.batchnormal3f = NULL;
8994 rsurface.batchnormal3f_vertexbuffer = NULL;
8995 rsurface.batchnormal3f_bufferoffset = 0;
8996 rsurface.batchlightmapcolor4f = NULL;
8997 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8998 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8999 rsurface.batchtexcoordtexture2f = NULL;
9000 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9001 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9002 rsurface.batchtexcoordlightmap2f = NULL;
9003 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9004 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9005 rsurface.batchskeletalindex4ub = NULL;
9006 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9007 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9008 rsurface.batchskeletalweight4ub = NULL;
9009 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9010 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9011 rsurface.batchvertexmesh = NULL;
9012 rsurface.batchvertexmesh_vertexbuffer = NULL;
9013 rsurface.batchvertexmesh_bufferoffset = 0;
9014 rsurface.batchelement3i = NULL;
9015 rsurface.batchelement3i_indexbuffer = NULL;
9016 rsurface.batchelement3i_bufferoffset = 0;
9017 rsurface.batchelement3s = NULL;
9018 rsurface.batchelement3s_indexbuffer = NULL;
9019 rsurface.batchelement3s_bufferoffset = 0;
9020 rsurface.passcolor4f = NULL;
9021 rsurface.passcolor4f_vertexbuffer = NULL;
9022 rsurface.passcolor4f_bufferoffset = 0;
9023 rsurface.forcecurrenttextureupdate = false;
9026 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)
9028 rsurface.entity = r_refdef.scene.worldentity;
9029 rsurface.skeleton = NULL;
9030 rsurface.ent_skinnum = 0;
9031 rsurface.ent_qwskin = -1;
9032 rsurface.ent_flags = entflags;
9033 rsurface.shadertime = r_refdef.scene.time - shadertime;
9034 rsurface.modelnumvertices = numvertices;
9035 rsurface.modelnumtriangles = numtriangles;
9036 rsurface.matrix = *matrix;
9037 rsurface.inversematrix = *inversematrix;
9038 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9039 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9040 R_EntityMatrix(&rsurface.matrix);
9041 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9042 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9043 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9044 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9045 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9046 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9047 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9048 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9049 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9050 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9051 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9052 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9053 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
9054 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9055 rsurface.frameblend[0].lerp = 1;
9056 rsurface.ent_alttextures = false;
9057 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9058 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9059 rsurface.entityskeletaltransform3x4 = NULL;
9060 rsurface.entityskeletaltransform3x4buffer = NULL;
9061 rsurface.entityskeletaltransform3x4offset = 0;
9062 rsurface.entityskeletaltransform3x4size = 0;
9063 rsurface.entityskeletalnumtransforms = 0;
9064 r_refdef.stats[r_stat_batch_entitycustom_count]++;
9065 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9066 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9067 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9070 rsurface.modelvertex3f = (float *)vertex3f;
9071 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9072 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9073 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9075 else if (wantnormals)
9077 rsurface.modelvertex3f = (float *)vertex3f;
9078 rsurface.modelsvector3f = NULL;
9079 rsurface.modeltvector3f = NULL;
9080 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9084 rsurface.modelvertex3f = (float *)vertex3f;
9085 rsurface.modelsvector3f = NULL;
9086 rsurface.modeltvector3f = NULL;
9087 rsurface.modelnormal3f = NULL;
9089 rsurface.modelvertexmesh = NULL;
9090 rsurface.modelvertexmesh_vertexbuffer = NULL;
9091 rsurface.modelvertexmesh_bufferoffset = 0;
9092 rsurface.modelvertex3f_vertexbuffer = 0;
9093 rsurface.modelvertex3f_bufferoffset = 0;
9094 rsurface.modelsvector3f_vertexbuffer = 0;
9095 rsurface.modelsvector3f_bufferoffset = 0;
9096 rsurface.modeltvector3f_vertexbuffer = 0;
9097 rsurface.modeltvector3f_bufferoffset = 0;
9098 rsurface.modelnormal3f_vertexbuffer = 0;
9099 rsurface.modelnormal3f_bufferoffset = 0;
9100 rsurface.modelgeneratedvertex = true;
9101 rsurface.modellightmapcolor4f = (float *)color4f;
9102 rsurface.modellightmapcolor4f_vertexbuffer = 0;
9103 rsurface.modellightmapcolor4f_bufferoffset = 0;
9104 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
9105 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9106 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9107 rsurface.modeltexcoordlightmap2f = NULL;
9108 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9109 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9110 rsurface.modelskeletalindex4ub = NULL;
9111 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9112 rsurface.modelskeletalindex4ub_bufferoffset = 0;
9113 rsurface.modelskeletalweight4ub = NULL;
9114 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9115 rsurface.modelskeletalweight4ub_bufferoffset = 0;
9116 rsurface.modelelement3i = (int *)element3i;
9117 rsurface.modelelement3i_indexbuffer = NULL;
9118 rsurface.modelelement3i_bufferoffset = 0;
9119 rsurface.modelelement3s = (unsigned short *)element3s;
9120 rsurface.modelelement3s_indexbuffer = NULL;
9121 rsurface.modelelement3s_bufferoffset = 0;
9122 rsurface.modellightmapoffsets = NULL;
9123 rsurface.modelsurfaces = NULL;
9124 rsurface.batchgeneratedvertex = false;
9125 rsurface.batchfirstvertex = 0;
9126 rsurface.batchnumvertices = 0;
9127 rsurface.batchfirsttriangle = 0;
9128 rsurface.batchnumtriangles = 0;
9129 rsurface.batchvertex3f = NULL;
9130 rsurface.batchvertex3f_vertexbuffer = NULL;
9131 rsurface.batchvertex3f_bufferoffset = 0;
9132 rsurface.batchsvector3f = NULL;
9133 rsurface.batchsvector3f_vertexbuffer = NULL;
9134 rsurface.batchsvector3f_bufferoffset = 0;
9135 rsurface.batchtvector3f = NULL;
9136 rsurface.batchtvector3f_vertexbuffer = NULL;
9137 rsurface.batchtvector3f_bufferoffset = 0;
9138 rsurface.batchnormal3f = NULL;
9139 rsurface.batchnormal3f_vertexbuffer = NULL;
9140 rsurface.batchnormal3f_bufferoffset = 0;
9141 rsurface.batchlightmapcolor4f = NULL;
9142 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9143 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9144 rsurface.batchtexcoordtexture2f = NULL;
9145 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9146 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9147 rsurface.batchtexcoordlightmap2f = NULL;
9148 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9149 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9150 rsurface.batchskeletalindex4ub = NULL;
9151 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9152 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9153 rsurface.batchskeletalweight4ub = NULL;
9154 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9155 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9156 rsurface.batchvertexmesh = NULL;
9157 rsurface.batchvertexmesh_vertexbuffer = NULL;
9158 rsurface.batchvertexmesh_bufferoffset = 0;
9159 rsurface.batchelement3i = NULL;
9160 rsurface.batchelement3i_indexbuffer = NULL;
9161 rsurface.batchelement3i_bufferoffset = 0;
9162 rsurface.batchelement3s = NULL;
9163 rsurface.batchelement3s_indexbuffer = NULL;
9164 rsurface.batchelement3s_bufferoffset = 0;
9165 rsurface.passcolor4f = NULL;
9166 rsurface.passcolor4f_vertexbuffer = NULL;
9167 rsurface.passcolor4f_bufferoffset = 0;
9168 rsurface.forcecurrenttextureupdate = true;
9170 if (rsurface.modelnumvertices && rsurface.modelelement3i)
9172 if ((wantnormals || wanttangents) && !normal3f)
9174 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9175 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9177 if (wanttangents && !svector3f)
9179 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9180 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9181 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9186 float RSurf_FogPoint(const float *v)
9188 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9189 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9190 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9191 float FogHeightFade = r_refdef.fogheightfade;
9193 unsigned int fogmasktableindex;
9194 if (r_refdef.fogplaneviewabove)
9195 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9197 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9198 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9199 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9202 float RSurf_FogVertex(const float *v)
9204 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9205 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9206 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9207 float FogHeightFade = rsurface.fogheightfade;
9209 unsigned int fogmasktableindex;
9210 if (r_refdef.fogplaneviewabove)
9211 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9213 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9214 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9215 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9218 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9221 for (i = 0;i < numelements;i++)
9222 outelement3i[i] = inelement3i[i] + adjust;
9225 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9226 extern cvar_t gl_vbo;
9227 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9235 int surfacefirsttriangle;
9236 int surfacenumtriangles;
9237 int surfacefirstvertex;
9238 int surfaceendvertex;
9239 int surfacenumvertices;
9240 int batchnumsurfaces = texturenumsurfaces;
9241 int batchnumvertices;
9242 int batchnumtriangles;
9246 qboolean dynamicvertex;
9249 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9252 q3shaderinfo_deform_t *deform;
9253 const msurface_t *surface, *firstsurface;
9254 r_vertexmesh_t *vertexmesh;
9255 if (!texturenumsurfaces)
9257 // find vertex range of this surface batch
9259 firstsurface = texturesurfacelist[0];
9260 firsttriangle = firstsurface->num_firsttriangle;
9261 batchnumvertices = 0;
9262 batchnumtriangles = 0;
9263 firstvertex = endvertex = firstsurface->num_firstvertex;
9264 for (i = 0;i < texturenumsurfaces;i++)
9266 surface = texturesurfacelist[i];
9267 if (surface != firstsurface + i)
9269 surfacefirstvertex = surface->num_firstvertex;
9270 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9271 surfacenumvertices = surface->num_vertices;
9272 surfacenumtriangles = surface->num_triangles;
9273 if (firstvertex > surfacefirstvertex)
9274 firstvertex = surfacefirstvertex;
9275 if (endvertex < surfaceendvertex)
9276 endvertex = surfaceendvertex;
9277 batchnumvertices += surfacenumvertices;
9278 batchnumtriangles += surfacenumtriangles;
9281 r_refdef.stats[r_stat_batch_batches]++;
9283 r_refdef.stats[r_stat_batch_withgaps]++;
9284 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9285 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9286 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9288 // we now know the vertex range used, and if there are any gaps in it
9289 rsurface.batchfirstvertex = firstvertex;
9290 rsurface.batchnumvertices = endvertex - firstvertex;
9291 rsurface.batchfirsttriangle = firsttriangle;
9292 rsurface.batchnumtriangles = batchnumtriangles;
9294 // this variable holds flags for which properties have been updated that
9295 // may require regenerating vertexmesh array...
9298 // check if any dynamic vertex processing must occur
9299 dynamicvertex = false;
9301 // a cvar to force the dynamic vertex path to be taken, for debugging
9302 if (r_batch_debugdynamicvertexpath.integer)
9306 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9307 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9308 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9309 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9311 dynamicvertex = true;
9314 // if there is a chance of animated vertex colors, it's a dynamic batch
9315 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9319 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9320 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9321 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9322 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9324 dynamicvertex = true;
9325 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9328 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9330 switch (deform->deform)
9333 case Q3DEFORM_PROJECTIONSHADOW:
9334 case Q3DEFORM_TEXT0:
9335 case Q3DEFORM_TEXT1:
9336 case Q3DEFORM_TEXT2:
9337 case Q3DEFORM_TEXT3:
9338 case Q3DEFORM_TEXT4:
9339 case Q3DEFORM_TEXT5:
9340 case Q3DEFORM_TEXT6:
9341 case Q3DEFORM_TEXT7:
9344 case Q3DEFORM_AUTOSPRITE:
9347 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9348 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9349 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9350 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9352 dynamicvertex = true;
9353 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9354 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9356 case Q3DEFORM_AUTOSPRITE2:
9359 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9360 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9361 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9362 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9364 dynamicvertex = true;
9365 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9366 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9368 case Q3DEFORM_NORMAL:
9371 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9372 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9373 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9374 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9376 dynamicvertex = true;
9377 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9378 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9381 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9382 break; // if wavefunc is a nop, ignore this transform
9385 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9386 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9387 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9388 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9390 dynamicvertex = true;
9391 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9392 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9394 case Q3DEFORM_BULGE:
9397 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9398 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9399 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9400 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9402 dynamicvertex = true;
9403 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9404 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9407 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9408 break; // if wavefunc is a nop, ignore this transform
9411 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9412 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9413 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9414 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9416 dynamicvertex = true;
9417 batchneed |= BATCHNEED_ARRAY_VERTEX;
9418 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9422 if (rsurface.texture->materialshaderpass)
9424 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9427 case Q3TCGEN_TEXTURE:
9429 case Q3TCGEN_LIGHTMAP:
9432 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9433 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9434 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9435 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9437 dynamicvertex = true;
9438 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9439 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9441 case Q3TCGEN_VECTOR:
9444 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9445 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9446 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9447 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9449 dynamicvertex = true;
9450 batchneed |= BATCHNEED_ARRAY_VERTEX;
9451 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9453 case Q3TCGEN_ENVIRONMENT:
9456 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9457 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9458 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9459 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9461 dynamicvertex = true;
9462 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9463 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9466 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9470 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9471 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9472 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9473 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9475 dynamicvertex = true;
9476 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9477 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9481 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9485 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9486 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9487 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9488 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9490 dynamicvertex = true;
9491 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9494 // when the model data has no vertex buffer (dynamic mesh), we need to
9496 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9497 batchneed |= BATCHNEED_NOGAPS;
9499 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9500 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9501 // we ensure this by treating the vertex batch as dynamic...
9502 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9506 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9507 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9508 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9509 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9511 dynamicvertex = true;
9516 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9517 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9518 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9519 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9520 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9521 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9522 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9523 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9526 // if needsupdate, we have to do a dynamic vertex batch for sure
9527 if (needsupdate & batchneed)
9531 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9532 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9533 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9534 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9536 dynamicvertex = true;
9539 // see if we need to build vertexmesh from arrays
9540 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9544 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9545 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9546 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9547 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9549 dynamicvertex = true;
9552 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9553 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9554 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9556 rsurface.batchvertex3f = rsurface.modelvertex3f;
9557 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9558 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9559 rsurface.batchsvector3f = rsurface.modelsvector3f;
9560 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9561 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9562 rsurface.batchtvector3f = rsurface.modeltvector3f;
9563 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9564 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9565 rsurface.batchnormal3f = rsurface.modelnormal3f;
9566 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9567 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9568 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9569 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9570 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9571 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9572 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9573 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9574 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9575 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9576 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9577 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9578 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9579 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9580 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9581 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9582 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9583 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9584 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9585 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9586 rsurface.batchelement3i = rsurface.modelelement3i;
9587 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9588 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9589 rsurface.batchelement3s = rsurface.modelelement3s;
9590 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9591 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9592 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9593 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9594 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9595 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9596 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9598 // if any dynamic vertex processing has to occur in software, we copy the
9599 // entire surface list together before processing to rebase the vertices
9600 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9602 // if any gaps exist and we do not have a static vertex buffer, we have to
9603 // copy the surface list together to avoid wasting upload bandwidth on the
9604 // vertices in the gaps.
9606 // if gaps exist and we have a static vertex buffer, we can choose whether
9607 // to combine the index buffer ranges into one dynamic index buffer or
9608 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9610 // in many cases the batch is reduced to one draw call.
9612 rsurface.batchmultidraw = false;
9613 rsurface.batchmultidrawnumsurfaces = 0;
9614 rsurface.batchmultidrawsurfacelist = NULL;
9618 // static vertex data, just set pointers...
9619 rsurface.batchgeneratedvertex = false;
9620 // if there are gaps, we want to build a combined index buffer,
9621 // otherwise use the original static buffer with an appropriate offset
9624 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9625 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9626 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9627 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9628 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9630 rsurface.batchmultidraw = true;
9631 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9632 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9635 // build a new triangle elements array for this batch
9636 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9637 rsurface.batchfirsttriangle = 0;
9639 for (i = 0;i < texturenumsurfaces;i++)
9641 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9642 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9643 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9644 numtriangles += surfacenumtriangles;
9646 rsurface.batchelement3i_indexbuffer = NULL;
9647 rsurface.batchelement3i_bufferoffset = 0;
9648 rsurface.batchelement3s = NULL;
9649 rsurface.batchelement3s_indexbuffer = NULL;
9650 rsurface.batchelement3s_bufferoffset = 0;
9651 if (endvertex <= 65536)
9653 // make a 16bit (unsigned short) index array if possible
9654 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9655 for (i = 0;i < numtriangles*3;i++)
9656 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9658 // upload buffer data for the copytriangles batch
9659 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9661 if (rsurface.batchelement3s)
9662 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9663 else if (rsurface.batchelement3i)
9664 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9669 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9670 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9671 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9672 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9677 // something needs software processing, do it for real...
9678 // we only directly handle separate array data in this case and then
9679 // generate interleaved data if needed...
9680 rsurface.batchgeneratedvertex = true;
9681 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9682 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9683 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9684 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9686 // now copy the vertex data into a combined array and make an index array
9687 // (this is what Quake3 does all the time)
9688 // we also apply any skeletal animation here that would have been done in
9689 // the vertex shader, because most of the dynamic vertex animation cases
9690 // need actual vertex positions and normals
9691 //if (dynamicvertex)
9693 rsurface.batchvertexmesh = NULL;
9694 rsurface.batchvertexmesh_vertexbuffer = NULL;
9695 rsurface.batchvertexmesh_bufferoffset = 0;
9696 rsurface.batchvertex3f = NULL;
9697 rsurface.batchvertex3f_vertexbuffer = NULL;
9698 rsurface.batchvertex3f_bufferoffset = 0;
9699 rsurface.batchsvector3f = NULL;
9700 rsurface.batchsvector3f_vertexbuffer = NULL;
9701 rsurface.batchsvector3f_bufferoffset = 0;
9702 rsurface.batchtvector3f = NULL;
9703 rsurface.batchtvector3f_vertexbuffer = NULL;
9704 rsurface.batchtvector3f_bufferoffset = 0;
9705 rsurface.batchnormal3f = NULL;
9706 rsurface.batchnormal3f_vertexbuffer = NULL;
9707 rsurface.batchnormal3f_bufferoffset = 0;
9708 rsurface.batchlightmapcolor4f = NULL;
9709 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9710 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9711 rsurface.batchtexcoordtexture2f = NULL;
9712 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9713 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9714 rsurface.batchtexcoordlightmap2f = NULL;
9715 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9716 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9717 rsurface.batchskeletalindex4ub = NULL;
9718 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9719 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9720 rsurface.batchskeletalweight4ub = NULL;
9721 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9722 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9723 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9724 rsurface.batchelement3i_indexbuffer = NULL;
9725 rsurface.batchelement3i_bufferoffset = 0;
9726 rsurface.batchelement3s = NULL;
9727 rsurface.batchelement3s_indexbuffer = NULL;
9728 rsurface.batchelement3s_bufferoffset = 0;
9729 rsurface.batchskeletaltransform3x4buffer = NULL;
9730 rsurface.batchskeletaltransform3x4offset = 0;
9731 rsurface.batchskeletaltransform3x4size = 0;
9732 // we'll only be setting up certain arrays as needed
9733 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9734 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9735 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9736 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9737 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9738 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9739 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9741 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9742 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9744 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9745 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9746 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9747 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9748 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9749 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9750 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9752 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9753 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9757 for (i = 0;i < texturenumsurfaces;i++)
9759 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9760 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9761 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9762 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9763 // copy only the data requested
9764 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9765 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9766 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9768 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9770 if (rsurface.batchvertex3f)
9771 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9773 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9775 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9777 if (rsurface.modelnormal3f)
9778 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9780 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9782 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9784 if (rsurface.modelsvector3f)
9786 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9787 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9791 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9792 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9795 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9797 if (rsurface.modellightmapcolor4f)
9798 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9800 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9802 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9804 if (rsurface.modeltexcoordtexture2f)
9805 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9807 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9809 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9811 if (rsurface.modeltexcoordlightmap2f)
9812 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9814 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9816 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9818 if (rsurface.modelskeletalindex4ub)
9820 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9821 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9825 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9826 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9827 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9828 for (j = 0;j < surfacenumvertices;j++)
9833 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9834 numvertices += surfacenumvertices;
9835 numtriangles += surfacenumtriangles;
9838 // generate a 16bit index array as well if possible
9839 // (in general, dynamic batches fit)
9840 if (numvertices <= 65536)
9842 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9843 for (i = 0;i < numtriangles*3;i++)
9844 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9847 // since we've copied everything, the batch now starts at 0
9848 rsurface.batchfirstvertex = 0;
9849 rsurface.batchnumvertices = batchnumvertices;
9850 rsurface.batchfirsttriangle = 0;
9851 rsurface.batchnumtriangles = batchnumtriangles;
9854 // apply skeletal animation that would have been done in the vertex shader
9855 if (rsurface.batchskeletaltransform3x4)
9857 const unsigned char *si;
9858 const unsigned char *sw;
9860 const float *b = rsurface.batchskeletaltransform3x4;
9861 float *vp, *vs, *vt, *vn;
9863 float m[3][4], n[3][4];
9864 float tp[3], ts[3], tt[3], tn[3];
9865 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9866 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9867 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9868 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9869 si = rsurface.batchskeletalindex4ub;
9870 sw = rsurface.batchskeletalweight4ub;
9871 vp = rsurface.batchvertex3f;
9872 vs = rsurface.batchsvector3f;
9873 vt = rsurface.batchtvector3f;
9874 vn = rsurface.batchnormal3f;
9875 memset(m[0], 0, sizeof(m));
9876 memset(n[0], 0, sizeof(n));
9877 for (i = 0;i < batchnumvertices;i++)
9879 t[0] = b + si[0]*12;
9882 // common case - only one matrix
9896 else if (sw[2] + sw[3])
9899 t[1] = b + si[1]*12;
9900 t[2] = b + si[2]*12;
9901 t[3] = b + si[3]*12;
9902 w[0] = sw[0] * (1.0f / 255.0f);
9903 w[1] = sw[1] * (1.0f / 255.0f);
9904 w[2] = sw[2] * (1.0f / 255.0f);
9905 w[3] = sw[3] * (1.0f / 255.0f);
9906 // blend the matrices
9907 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9908 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9909 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9910 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9911 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9912 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9913 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9914 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9915 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9916 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9917 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9918 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9923 t[1] = b + si[1]*12;
9924 w[0] = sw[0] * (1.0f / 255.0f);
9925 w[1] = sw[1] * (1.0f / 255.0f);
9926 // blend the matrices
9927 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9928 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9929 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9930 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9931 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9932 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9933 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9934 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9935 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9936 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9937 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9938 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9942 // modify the vertex
9944 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9945 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9946 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9950 // the normal transformation matrix is a set of cross products...
9951 CrossProduct(m[1], m[2], n[0]);
9952 CrossProduct(m[2], m[0], n[1]);
9953 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9955 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9956 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9957 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9958 VectorNormalize(vn);
9963 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9964 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9965 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9966 VectorNormalize(vs);
9969 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9970 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9971 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9972 VectorNormalize(vt);
9977 rsurface.batchskeletaltransform3x4 = NULL;
9978 rsurface.batchskeletalnumtransforms = 0;
9981 // q1bsp surfaces rendered in vertex color mode have to have colors
9982 // calculated based on lightstyles
9983 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9985 // generate color arrays for the surfaces in this list
9990 const unsigned char *lm;
9991 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9992 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9993 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9995 for (i = 0;i < texturenumsurfaces;i++)
9997 surface = texturesurfacelist[i];
9998 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9999 surfacenumvertices = surface->num_vertices;
10000 if (surface->lightmapinfo->samples)
10002 for (j = 0;j < surfacenumvertices;j++)
10004 lm = surface->lightmapinfo->samples + offsets[j];
10005 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10006 VectorScale(lm, scale, c);
10007 if (surface->lightmapinfo->styles[1] != 255)
10009 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10011 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10012 VectorMA(c, scale, lm, c);
10013 if (surface->lightmapinfo->styles[2] != 255)
10016 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10017 VectorMA(c, scale, lm, c);
10018 if (surface->lightmapinfo->styles[3] != 255)
10021 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10022 VectorMA(c, scale, lm, c);
10029 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);
10035 for (j = 0;j < surfacenumvertices;j++)
10037 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10044 // if vertices are deformed (sprite flares and things in maps, possibly
10045 // water waves, bulges and other deformations), modify the copied vertices
10047 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
10050 switch (deform->deform)
10053 case Q3DEFORM_PROJECTIONSHADOW:
10054 case Q3DEFORM_TEXT0:
10055 case Q3DEFORM_TEXT1:
10056 case Q3DEFORM_TEXT2:
10057 case Q3DEFORM_TEXT3:
10058 case Q3DEFORM_TEXT4:
10059 case Q3DEFORM_TEXT5:
10060 case Q3DEFORM_TEXT6:
10061 case Q3DEFORM_TEXT7:
10062 case Q3DEFORM_NONE:
10064 case Q3DEFORM_AUTOSPRITE:
10065 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10066 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10067 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10068 VectorNormalize(newforward);
10069 VectorNormalize(newright);
10070 VectorNormalize(newup);
10071 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10072 // rsurface.batchvertex3f_vertexbuffer = NULL;
10073 // rsurface.batchvertex3f_bufferoffset = 0;
10074 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10075 // rsurface.batchsvector3f_vertexbuffer = NULL;
10076 // rsurface.batchsvector3f_bufferoffset = 0;
10077 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10078 // rsurface.batchtvector3f_vertexbuffer = NULL;
10079 // rsurface.batchtvector3f_bufferoffset = 0;
10080 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10081 // rsurface.batchnormal3f_vertexbuffer = NULL;
10082 // rsurface.batchnormal3f_bufferoffset = 0;
10083 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10084 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10085 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10086 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10087 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);
10088 // a single autosprite surface can contain multiple sprites...
10089 for (j = 0;j < batchnumvertices - 3;j += 4)
10091 VectorClear(center);
10092 for (i = 0;i < 4;i++)
10093 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10094 VectorScale(center, 0.25f, center);
10095 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10096 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10097 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10098 for (i = 0;i < 4;i++)
10100 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10101 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10104 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10105 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10106 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);
10108 case Q3DEFORM_AUTOSPRITE2:
10109 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10110 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10111 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10112 VectorNormalize(newforward);
10113 VectorNormalize(newright);
10114 VectorNormalize(newup);
10115 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10116 // rsurface.batchvertex3f_vertexbuffer = NULL;
10117 // rsurface.batchvertex3f_bufferoffset = 0;
10119 const float *v1, *v2;
10129 memset(shortest, 0, sizeof(shortest));
10130 // a single autosprite surface can contain multiple sprites...
10131 for (j = 0;j < batchnumvertices - 3;j += 4)
10133 VectorClear(center);
10134 for (i = 0;i < 4;i++)
10135 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10136 VectorScale(center, 0.25f, center);
10137 // find the two shortest edges, then use them to define the
10138 // axis vectors for rotating around the central axis
10139 for (i = 0;i < 6;i++)
10141 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10142 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10143 l = VectorDistance2(v1, v2);
10144 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10145 if (v1[2] != v2[2])
10146 l += (1.0f / 1024.0f);
10147 if (shortest[0].length2 > l || i == 0)
10149 shortest[1] = shortest[0];
10150 shortest[0].length2 = l;
10151 shortest[0].v1 = v1;
10152 shortest[0].v2 = v2;
10154 else if (shortest[1].length2 > l || i == 1)
10156 shortest[1].length2 = l;
10157 shortest[1].v1 = v1;
10158 shortest[1].v2 = v2;
10161 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10162 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10163 // this calculates the right vector from the shortest edge
10164 // and the up vector from the edge midpoints
10165 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10166 VectorNormalize(right);
10167 VectorSubtract(end, start, up);
10168 VectorNormalize(up);
10169 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10170 VectorSubtract(rsurface.localvieworigin, center, forward);
10171 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10172 VectorNegate(forward, forward);
10173 VectorReflect(forward, 0, up, forward);
10174 VectorNormalize(forward);
10175 CrossProduct(up, forward, newright);
10176 VectorNormalize(newright);
10177 // rotate the quad around the up axis vector, this is made
10178 // especially easy by the fact we know the quad is flat,
10179 // so we only have to subtract the center position and
10180 // measure distance along the right vector, and then
10181 // multiply that by the newright vector and add back the
10183 // we also need to subtract the old position to undo the
10184 // displacement from the center, which we do with a
10185 // DotProduct, the subtraction/addition of center is also
10186 // optimized into DotProducts here
10187 l = DotProduct(right, center);
10188 for (i = 0;i < 4;i++)
10190 v1 = rsurface.batchvertex3f + 3*(j+i);
10191 f = DotProduct(right, v1) - l;
10192 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10196 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10198 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10199 // rsurface.batchnormal3f_vertexbuffer = NULL;
10200 // rsurface.batchnormal3f_bufferoffset = 0;
10201 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10203 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10205 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10206 // rsurface.batchsvector3f_vertexbuffer = NULL;
10207 // rsurface.batchsvector3f_bufferoffset = 0;
10208 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10209 // rsurface.batchtvector3f_vertexbuffer = NULL;
10210 // rsurface.batchtvector3f_bufferoffset = 0;
10211 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);
10214 case Q3DEFORM_NORMAL:
10215 // deform the normals to make reflections wavey
10216 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10217 rsurface.batchnormal3f_vertexbuffer = NULL;
10218 rsurface.batchnormal3f_bufferoffset = 0;
10219 for (j = 0;j < batchnumvertices;j++)
10222 float *normal = rsurface.batchnormal3f + 3*j;
10223 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10224 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10225 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10226 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10227 VectorNormalize(normal);
10229 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10231 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10232 // rsurface.batchsvector3f_vertexbuffer = NULL;
10233 // rsurface.batchsvector3f_bufferoffset = 0;
10234 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10235 // rsurface.batchtvector3f_vertexbuffer = NULL;
10236 // rsurface.batchtvector3f_bufferoffset = 0;
10237 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);
10240 case Q3DEFORM_WAVE:
10241 // deform vertex array to make wavey water and flags and such
10242 waveparms[0] = deform->waveparms[0];
10243 waveparms[1] = deform->waveparms[1];
10244 waveparms[2] = deform->waveparms[2];
10245 waveparms[3] = deform->waveparms[3];
10246 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10247 break; // if wavefunc is a nop, don't make a dynamic vertex array
10248 // this is how a divisor of vertex influence on deformation
10249 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10250 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10251 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10252 // rsurface.batchvertex3f_vertexbuffer = NULL;
10253 // rsurface.batchvertex3f_bufferoffset = 0;
10254 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10255 // rsurface.batchnormal3f_vertexbuffer = NULL;
10256 // rsurface.batchnormal3f_bufferoffset = 0;
10257 for (j = 0;j < batchnumvertices;j++)
10259 // if the wavefunc depends on time, evaluate it per-vertex
10262 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10263 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10265 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10267 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10268 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10269 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10271 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10272 // rsurface.batchsvector3f_vertexbuffer = NULL;
10273 // rsurface.batchsvector3f_bufferoffset = 0;
10274 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10275 // rsurface.batchtvector3f_vertexbuffer = NULL;
10276 // rsurface.batchtvector3f_bufferoffset = 0;
10277 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);
10280 case Q3DEFORM_BULGE:
10281 // deform vertex array to make the surface have moving bulges
10282 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10283 // rsurface.batchvertex3f_vertexbuffer = NULL;
10284 // rsurface.batchvertex3f_bufferoffset = 0;
10285 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10286 // rsurface.batchnormal3f_vertexbuffer = NULL;
10287 // rsurface.batchnormal3f_bufferoffset = 0;
10288 for (j = 0;j < batchnumvertices;j++)
10290 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10291 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10293 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10294 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10295 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10297 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10298 // rsurface.batchsvector3f_vertexbuffer = NULL;
10299 // rsurface.batchsvector3f_bufferoffset = 0;
10300 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10301 // rsurface.batchtvector3f_vertexbuffer = NULL;
10302 // rsurface.batchtvector3f_bufferoffset = 0;
10303 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);
10306 case Q3DEFORM_MOVE:
10307 // deform vertex array
10308 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10309 break; // if wavefunc is a nop, don't make a dynamic vertex array
10310 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10311 VectorScale(deform->parms, scale, waveparms);
10312 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10313 // rsurface.batchvertex3f_vertexbuffer = NULL;
10314 // rsurface.batchvertex3f_bufferoffset = 0;
10315 for (j = 0;j < batchnumvertices;j++)
10316 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10321 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10323 // generate texcoords based on the chosen texcoord source
10324 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10327 case Q3TCGEN_TEXTURE:
10329 case Q3TCGEN_LIGHTMAP:
10330 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10331 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10332 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10333 if (rsurface.batchtexcoordlightmap2f)
10334 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10336 case Q3TCGEN_VECTOR:
10337 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10338 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10339 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10340 for (j = 0;j < batchnumvertices;j++)
10342 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10343 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10346 case Q3TCGEN_ENVIRONMENT:
10347 // make environment reflections using a spheremap
10348 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10349 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10350 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10351 for (j = 0;j < batchnumvertices;j++)
10353 // identical to Q3A's method, but executed in worldspace so
10354 // carried models can be shiny too
10356 float viewer[3], d, reflected[3], worldreflected[3];
10358 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10359 // VectorNormalize(viewer);
10361 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10363 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10364 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10365 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10366 // note: this is proportinal to viewer, so we can normalize later
10368 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10369 VectorNormalize(worldreflected);
10371 // note: this sphere map only uses world x and z!
10372 // so positive and negative y will LOOK THE SAME.
10373 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10374 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10378 // the only tcmod that needs software vertex processing is turbulent, so
10379 // check for it here and apply the changes if needed
10380 // and we only support that as the first one
10381 // (handling a mixture of turbulent and other tcmods would be problematic
10382 // without punting it entirely to a software path)
10383 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10385 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10386 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10387 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10388 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10389 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10390 for (j = 0;j < batchnumvertices;j++)
10392 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);
10393 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10398 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10400 // convert the modified arrays to vertex structs
10401 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10402 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10403 // rsurface.batchvertexmesh_bufferoffset = 0;
10404 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10405 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10406 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10407 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10408 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10409 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10410 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10412 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10414 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10415 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10418 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10419 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10420 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10421 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10422 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10423 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10424 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10425 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10426 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10427 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10429 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10431 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10432 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10437 // upload buffer data for the dynamic batch
10438 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10440 if (rsurface.batchvertexmesh)
10441 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10444 if (rsurface.batchvertex3f)
10445 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10446 if (rsurface.batchsvector3f)
10447 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10448 if (rsurface.batchtvector3f)
10449 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10450 if (rsurface.batchnormal3f)
10451 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10452 if (rsurface.batchlightmapcolor4f)
10453 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10454 if (rsurface.batchtexcoordtexture2f)
10455 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10456 if (rsurface.batchtexcoordlightmap2f)
10457 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10458 if (rsurface.batchskeletalindex4ub)
10459 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10460 if (rsurface.batchskeletalweight4ub)
10461 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10463 if (rsurface.batchelement3s)
10464 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10465 else if (rsurface.batchelement3i)
10466 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10470 void RSurf_DrawBatch(void)
10472 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10473 // through the pipeline, killing it earlier in the pipeline would have
10474 // per-surface overhead rather than per-batch overhead, so it's best to
10475 // reject it here, before it hits glDraw.
10476 if (rsurface.batchnumtriangles == 0)
10479 // batch debugging code
10480 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10486 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10487 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10490 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10492 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10494 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10495 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);
10502 if (rsurface.batchmultidraw)
10504 // issue multiple draws rather than copying index data
10505 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10506 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10507 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10508 for (i = 0;i < numsurfaces;)
10510 // combine consecutive surfaces as one draw
10511 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10512 if (surfacelist[j] != surfacelist[k] + 1)
10514 firstvertex = surfacelist[i]->num_firstvertex;
10515 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10516 firsttriangle = surfacelist[i]->num_firsttriangle;
10517 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10518 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);
10524 // there is only one consecutive run of index data (may have been combined)
10525 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);
10529 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10531 // pick the closest matching water plane
10532 int planeindex, vertexindex, bestplaneindex = -1;
10536 r_waterstate_waterplane_t *p;
10537 qboolean prepared = false;
10539 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10541 if(p->camera_entity != rsurface.texture->camera_entity)
10546 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10548 if(rsurface.batchnumvertices == 0)
10551 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10553 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10554 d += fabs(PlaneDiff(vert, &p->plane));
10556 if (bestd > d || bestplaneindex < 0)
10559 bestplaneindex = planeindex;
10562 return bestplaneindex;
10563 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10564 // this situation though, as it might be better to render single larger
10565 // batches with useless stuff (backface culled for example) than to
10566 // render multiple smaller batches
10569 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10572 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10573 rsurface.passcolor4f_vertexbuffer = 0;
10574 rsurface.passcolor4f_bufferoffset = 0;
10575 for (i = 0;i < rsurface.batchnumvertices;i++)
10576 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10579 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10586 if (rsurface.passcolor4f)
10588 // generate color arrays
10589 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10590 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10591 rsurface.passcolor4f_vertexbuffer = 0;
10592 rsurface.passcolor4f_bufferoffset = 0;
10593 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)
10595 f = RSurf_FogVertex(v);
10604 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10605 rsurface.passcolor4f_vertexbuffer = 0;
10606 rsurface.passcolor4f_bufferoffset = 0;
10607 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10609 f = RSurf_FogVertex(v);
10618 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10625 if (!rsurface.passcolor4f)
10627 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10628 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10629 rsurface.passcolor4f_vertexbuffer = 0;
10630 rsurface.passcolor4f_bufferoffset = 0;
10631 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)
10633 f = RSurf_FogVertex(v);
10634 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10635 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10636 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10641 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10646 if (!rsurface.passcolor4f)
10648 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10649 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10650 rsurface.passcolor4f_vertexbuffer = 0;
10651 rsurface.passcolor4f_bufferoffset = 0;
10652 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10661 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10666 if (!rsurface.passcolor4f)
10668 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10669 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10670 rsurface.passcolor4f_vertexbuffer = 0;
10671 rsurface.passcolor4f_bufferoffset = 0;
10672 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10674 c2[0] = c[0] + r_refdef.scene.ambient;
10675 c2[1] = c[1] + r_refdef.scene.ambient;
10676 c2[2] = c[2] + r_refdef.scene.ambient;
10681 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10684 rsurface.passcolor4f = NULL;
10685 rsurface.passcolor4f_vertexbuffer = 0;
10686 rsurface.passcolor4f_bufferoffset = 0;
10687 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10688 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10689 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10690 GL_Color(r, g, b, a);
10691 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10692 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10693 R_Mesh_TexMatrix(0, NULL);
10697 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10699 // TODO: optimize applyfog && applycolor case
10700 // just apply fog if necessary, and tint the fog color array if necessary
10701 rsurface.passcolor4f = NULL;
10702 rsurface.passcolor4f_vertexbuffer = 0;
10703 rsurface.passcolor4f_bufferoffset = 0;
10704 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10705 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10706 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10707 GL_Color(r, g, b, a);
10711 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10714 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10715 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10716 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10717 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10718 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10719 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10720 GL_Color(r, g, b, a);
10724 static void RSurf_DrawBatch_GL11_ClampColor(void)
10729 if (!rsurface.passcolor4f)
10731 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10733 c2[0] = bound(0.0f, c1[0], 1.0f);
10734 c2[1] = bound(0.0f, c1[1], 1.0f);
10735 c2[2] = bound(0.0f, c1[2], 1.0f);
10736 c2[3] = bound(0.0f, c1[3], 1.0f);
10740 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10750 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10751 rsurface.passcolor4f_vertexbuffer = 0;
10752 rsurface.passcolor4f_bufferoffset = 0;
10753 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)
10755 f = -DotProduct(r_refdef.view.forward, n);
10757 f = f * 0.85 + 0.15; // work around so stuff won't get black
10758 f *= r_refdef.lightmapintensity;
10759 Vector4Set(c, f, f, f, 1);
10763 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10765 RSurf_DrawBatch_GL11_ApplyFakeLight();
10766 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10767 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10768 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10769 GL_Color(r, g, b, a);
10773 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10781 vec3_t ambientcolor;
10782 vec3_t diffusecolor;
10786 VectorCopy(rsurface.modellight_lightdir, lightdir);
10787 f = 0.5f * r_refdef.lightmapintensity;
10788 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10789 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10790 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10791 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10792 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10793 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10795 if (VectorLength2(diffusecolor) > 0)
10797 // q3-style directional shading
10798 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10799 rsurface.passcolor4f_vertexbuffer = 0;
10800 rsurface.passcolor4f_bufferoffset = 0;
10801 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)
10803 if ((f = DotProduct(n, lightdir)) > 0)
10804 VectorMA(ambientcolor, f, diffusecolor, c);
10806 VectorCopy(ambientcolor, c);
10813 *applycolor = false;
10817 *r = ambientcolor[0];
10818 *g = ambientcolor[1];
10819 *b = ambientcolor[2];
10820 rsurface.passcolor4f = NULL;
10821 rsurface.passcolor4f_vertexbuffer = 0;
10822 rsurface.passcolor4f_bufferoffset = 0;
10826 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10828 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10829 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10830 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10831 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10832 GL_Color(r, g, b, a);
10836 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10844 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10845 rsurface.passcolor4f_vertexbuffer = 0;
10846 rsurface.passcolor4f_bufferoffset = 0;
10848 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10850 f = 1 - RSurf_FogVertex(v);
10858 void RSurf_SetupDepthAndCulling(void)
10860 // submodels are biased to avoid z-fighting with world surfaces that they
10861 // may be exactly overlapping (avoids z-fighting artifacts on certain
10862 // doors and things in Quake maps)
10863 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10864 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10865 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10866 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10869 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10872 // transparent sky would be ridiculous
10873 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10875 R_SetupShader_Generic_NoTexture(false, false);
10876 skyrenderlater = true;
10877 RSurf_SetupDepthAndCulling();
10878 GL_DepthMask(true);
10880 // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10881 if (r_sky_scissor.integer)
10883 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10884 for (i = 0; i < texturenumsurfaces; i++)
10886 const msurface_t *surf = texturesurfacelist[i];
10889 float mins[3], maxs[3];
10891 for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10893 Matrix4x4_Transform(&rsurface.matrix, v, p);
10896 if (mins[0] > p[0]) mins[0] = p[0];
10897 if (mins[1] > p[1]) mins[1] = p[1];
10898 if (mins[2] > p[2]) mins[2] = p[2];
10899 if (maxs[0] < p[0]) maxs[0] = p[0];
10900 if (maxs[1] < p[1]) maxs[1] = p[1];
10901 if (maxs[2] < p[2]) maxs[2] = p[2];
10905 VectorCopy(p, mins);
10906 VectorCopy(p, maxs);
10909 if (!R_ScissorForBBox(mins, maxs, scissor))
10913 if (skyscissor[0] > scissor[0])
10915 skyscissor[2] += skyscissor[0] - scissor[0];
10916 skyscissor[0] = scissor[0];
10918 if (skyscissor[1] > scissor[1])
10920 skyscissor[3] += skyscissor[1] - scissor[1];
10921 skyscissor[1] = scissor[1];
10923 if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10924 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10925 if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10926 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10929 Vector4Copy(scissor, skyscissor);
10934 // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10935 // skymasking on them, and Quake3 never did sky masking (unlike
10936 // software Quake and software Quake2), so disable the sky masking
10937 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10938 // and skymasking also looks very bad when noclipping outside the
10939 // level, so don't use it then either.
10940 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)
10942 R_Mesh_ResetTextureState();
10943 if (skyrendermasked)
10945 R_SetupShader_DepthOrShadow(false, false, false);
10946 // depth-only (masking)
10947 GL_ColorMask(0, 0, 0, 0);
10948 // just to make sure that braindead drivers don't draw
10949 // anything despite that colormask...
10950 GL_BlendFunc(GL_ZERO, GL_ONE);
10951 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10952 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10956 R_SetupShader_Generic_NoTexture(false, false);
10958 GL_BlendFunc(GL_ONE, GL_ZERO);
10959 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10960 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10961 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10964 if (skyrendermasked)
10965 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10967 R_Mesh_ResetTextureState();
10968 GL_Color(1, 1, 1, 1);
10971 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10972 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10973 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10975 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10979 // render screenspace normalmap to texture
10980 GL_DepthMask(true);
10981 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10986 // bind lightmap texture
10988 // water/refraction/reflection/camera surfaces have to be handled specially
10989 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10991 int start, end, startplaneindex;
10992 for (start = 0;start < texturenumsurfaces;start = end)
10994 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10995 if(startplaneindex < 0)
10997 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10998 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
11002 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
11004 // now that we have a batch using the same planeindex, render it
11005 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
11007 // render water or distortion background
11008 GL_DepthMask(true);
11009 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
11011 // blend surface on top
11012 GL_DepthMask(false);
11013 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
11016 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
11018 // render surface with reflection texture as input
11019 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11020 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
11027 // render surface batch normally
11028 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
11029 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
11033 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11035 // OpenGL 1.3 path - anything not completely ancient
11036 qboolean applycolor;
11039 const texturelayer_t *layer;
11040 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11041 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11043 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11046 int layertexrgbscale;
11047 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11049 if (layerindex == 0)
11050 GL_AlphaTest(true);
11053 GL_AlphaTest(false);
11054 GL_DepthFunc(GL_EQUAL);
11057 GL_DepthMask(layer->depthmask && writedepth);
11058 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11059 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11061 layertexrgbscale = 4;
11062 VectorScale(layer->color, 0.25f, layercolor);
11064 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11066 layertexrgbscale = 2;
11067 VectorScale(layer->color, 0.5f, layercolor);
11071 layertexrgbscale = 1;
11072 VectorScale(layer->color, 1.0f, layercolor);
11074 layercolor[3] = layer->color[3];
11075 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11076 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11077 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11078 switch (layer->type)
11080 case TEXTURELAYERTYPE_LITTEXTURE:
11081 // single-pass lightmapped texture with 2x rgbscale
11082 R_Mesh_TexBind(0, r_texture_white);
11083 R_Mesh_TexMatrix(0, NULL);
11084 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11085 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11086 R_Mesh_TexBind(1, layer->texture);
11087 R_Mesh_TexMatrix(1, &layer->texmatrix);
11088 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11089 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11090 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11091 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11092 else if (FAKELIGHT_ENABLED)
11093 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11094 else if (rsurface.uselightmaptexture)
11095 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11097 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11099 case TEXTURELAYERTYPE_TEXTURE:
11100 // singletexture unlit texture with transparency support
11101 R_Mesh_TexBind(0, layer->texture);
11102 R_Mesh_TexMatrix(0, &layer->texmatrix);
11103 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11104 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11105 R_Mesh_TexBind(1, 0);
11106 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11107 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11109 case TEXTURELAYERTYPE_FOG:
11110 // singletexture fogging
11111 if (layer->texture)
11113 R_Mesh_TexBind(0, layer->texture);
11114 R_Mesh_TexMatrix(0, &layer->texmatrix);
11115 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11116 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11120 R_Mesh_TexBind(0, 0);
11121 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11123 R_Mesh_TexBind(1, 0);
11124 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11125 // generate a color array for the fog pass
11126 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11127 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11131 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11134 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11136 GL_DepthFunc(GL_LEQUAL);
11137 GL_AlphaTest(false);
11141 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11143 // OpenGL 1.1 - crusty old voodoo path
11146 const texturelayer_t *layer;
11147 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11148 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11150 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11152 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11154 if (layerindex == 0)
11155 GL_AlphaTest(true);
11158 GL_AlphaTest(false);
11159 GL_DepthFunc(GL_EQUAL);
11162 GL_DepthMask(layer->depthmask && writedepth);
11163 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11164 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11165 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11166 switch (layer->type)
11168 case TEXTURELAYERTYPE_LITTEXTURE:
11169 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11171 // two-pass lit texture with 2x rgbscale
11172 // first the lightmap pass
11173 R_Mesh_TexBind(0, r_texture_white);
11174 R_Mesh_TexMatrix(0, NULL);
11175 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11176 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11177 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11178 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11179 else if (FAKELIGHT_ENABLED)
11180 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11181 else if (rsurface.uselightmaptexture)
11182 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11184 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11185 // then apply the texture to it
11186 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11187 R_Mesh_TexBind(0, layer->texture);
11188 R_Mesh_TexMatrix(0, &layer->texmatrix);
11189 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11190 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11191 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);
11195 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11196 R_Mesh_TexBind(0, layer->texture);
11197 R_Mesh_TexMatrix(0, &layer->texmatrix);
11198 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11199 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11200 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11201 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);
11202 else if (FAKELIGHT_ENABLED)
11203 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);
11205 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);
11208 case TEXTURELAYERTYPE_TEXTURE:
11209 // singletexture unlit texture with transparency support
11210 R_Mesh_TexBind(0, layer->texture);
11211 R_Mesh_TexMatrix(0, &layer->texmatrix);
11212 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11213 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11214 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);
11216 case TEXTURELAYERTYPE_FOG:
11217 // singletexture fogging
11218 if (layer->texture)
11220 R_Mesh_TexBind(0, layer->texture);
11221 R_Mesh_TexMatrix(0, &layer->texmatrix);
11222 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11223 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11227 R_Mesh_TexBind(0, 0);
11228 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11230 // generate a color array for the fog pass
11231 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11232 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11236 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11239 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11241 GL_DepthFunc(GL_LEQUAL);
11242 GL_AlphaTest(false);
11246 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11250 r_vertexgeneric_t *batchvertex;
11253 // R_Mesh_ResetTextureState();
11254 R_SetupShader_Generic_NoTexture(false, false);
11256 if(rsurface.texture && rsurface.texture->currentskinframe)
11258 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11259 c[3] *= rsurface.texture->currentalpha;
11269 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11271 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11272 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11273 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11276 // brighten it up (as texture value 127 means "unlit")
11277 c[0] *= 2 * r_refdef.view.colorscale;
11278 c[1] *= 2 * r_refdef.view.colorscale;
11279 c[2] *= 2 * r_refdef.view.colorscale;
11281 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11282 c[3] *= r_wateralpha.value;
11284 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11286 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11287 GL_DepthMask(false);
11289 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11291 GL_BlendFunc(GL_ONE, GL_ONE);
11292 GL_DepthMask(false);
11294 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11296 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11297 GL_DepthMask(false);
11299 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11301 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11302 GL_DepthMask(false);
11306 GL_BlendFunc(GL_ONE, GL_ZERO);
11307 GL_DepthMask(writedepth);
11310 if (r_showsurfaces.integer == 3)
11312 rsurface.passcolor4f = NULL;
11314 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11316 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11318 rsurface.passcolor4f = NULL;
11319 rsurface.passcolor4f_vertexbuffer = 0;
11320 rsurface.passcolor4f_bufferoffset = 0;
11322 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11324 qboolean applycolor = true;
11327 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11329 r_refdef.lightmapintensity = 1;
11330 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11331 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11333 else if (FAKELIGHT_ENABLED)
11335 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11337 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11338 RSurf_DrawBatch_GL11_ApplyFakeLight();
11339 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11343 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11345 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11346 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11347 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11350 if(!rsurface.passcolor4f)
11351 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11353 RSurf_DrawBatch_GL11_ApplyAmbient();
11354 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11355 if(r_refdef.fogenabled)
11356 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11357 RSurf_DrawBatch_GL11_ClampColor();
11359 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11360 R_SetupShader_Generic_NoTexture(false, false);
11363 else if (!r_refdef.view.showdebug)
11365 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11366 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11367 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11369 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11370 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11372 R_Mesh_PrepareVertices_Generic_Unlock();
11375 else if (r_showsurfaces.integer == 4)
11377 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11378 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11379 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11381 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11382 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11383 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11385 R_Mesh_PrepareVertices_Generic_Unlock();
11388 else if (r_showsurfaces.integer == 2)
11391 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11392 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11393 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11395 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11396 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11397 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11398 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11399 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11400 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11401 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11403 R_Mesh_PrepareVertices_Generic_Unlock();
11404 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11408 int texturesurfaceindex;
11410 const msurface_t *surface;
11411 float surfacecolor4f[4];
11412 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11413 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11415 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11417 surface = texturesurfacelist[texturesurfaceindex];
11418 k = (int)(((size_t)surface) / sizeof(msurface_t));
11419 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11420 for (j = 0;j < surface->num_vertices;j++)
11422 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11423 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11427 R_Mesh_PrepareVertices_Generic_Unlock();
11432 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11435 RSurf_SetupDepthAndCulling();
11436 if (r_showsurfaces.integer)
11438 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11441 switch (vid.renderpath)
11443 case RENDERPATH_GL20:
11444 case RENDERPATH_D3D9:
11445 case RENDERPATH_D3D10:
11446 case RENDERPATH_D3D11:
11447 case RENDERPATH_SOFT:
11448 case RENDERPATH_GLES2:
11449 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11451 case RENDERPATH_GL13:
11452 case RENDERPATH_GLES1:
11453 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11455 case RENDERPATH_GL11:
11456 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11462 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11465 RSurf_SetupDepthAndCulling();
11466 if (r_showsurfaces.integer)
11468 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11471 switch (vid.renderpath)
11473 case RENDERPATH_GL20:
11474 case RENDERPATH_D3D9:
11475 case RENDERPATH_D3D10:
11476 case RENDERPATH_D3D11:
11477 case RENDERPATH_SOFT:
11478 case RENDERPATH_GLES2:
11479 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11481 case RENDERPATH_GL13:
11482 case RENDERPATH_GLES1:
11483 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11485 case RENDERPATH_GL11:
11486 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11492 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11495 int texturenumsurfaces, endsurface;
11496 texture_t *texture;
11497 const msurface_t *surface;
11498 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11500 // if the model is static it doesn't matter what value we give for
11501 // wantnormals and wanttangents, so this logic uses only rules applicable
11502 // to a model, knowing that they are meaningless otherwise
11503 if (ent == r_refdef.scene.worldentity)
11504 RSurf_ActiveWorldEntity();
11505 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11506 RSurf_ActiveModelEntity(ent, false, false, false);
11509 switch (vid.renderpath)
11511 case RENDERPATH_GL20:
11512 case RENDERPATH_D3D9:
11513 case RENDERPATH_D3D10:
11514 case RENDERPATH_D3D11:
11515 case RENDERPATH_SOFT:
11516 case RENDERPATH_GLES2:
11517 RSurf_ActiveModelEntity(ent, true, true, false);
11519 case RENDERPATH_GL11:
11520 case RENDERPATH_GL13:
11521 case RENDERPATH_GLES1:
11522 RSurf_ActiveModelEntity(ent, true, false, false);
11527 if (r_transparentdepthmasking.integer)
11529 qboolean setup = false;
11530 for (i = 0;i < numsurfaces;i = j)
11533 surface = rsurface.modelsurfaces + surfacelist[i];
11534 texture = surface->texture;
11535 rsurface.texture = R_GetCurrentTexture(texture);
11536 rsurface.lightmaptexture = NULL;
11537 rsurface.deluxemaptexture = NULL;
11538 rsurface.uselightmaptexture = false;
11539 // scan ahead until we find a different texture
11540 endsurface = min(i + 1024, numsurfaces);
11541 texturenumsurfaces = 0;
11542 texturesurfacelist[texturenumsurfaces++] = surface;
11543 for (;j < endsurface;j++)
11545 surface = rsurface.modelsurfaces + surfacelist[j];
11546 if (texture != surface->texture)
11548 texturesurfacelist[texturenumsurfaces++] = surface;
11550 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11552 // render the range of surfaces as depth
11556 GL_ColorMask(0,0,0,0);
11558 GL_DepthTest(true);
11559 GL_BlendFunc(GL_ONE, GL_ZERO);
11560 GL_DepthMask(true);
11561 // R_Mesh_ResetTextureState();
11563 RSurf_SetupDepthAndCulling();
11564 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11565 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11566 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11570 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11573 for (i = 0;i < numsurfaces;i = j)
11576 surface = rsurface.modelsurfaces + surfacelist[i];
11577 texture = surface->texture;
11578 rsurface.texture = R_GetCurrentTexture(texture);
11579 // scan ahead until we find a different texture
11580 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11581 texturenumsurfaces = 0;
11582 texturesurfacelist[texturenumsurfaces++] = surface;
11583 if(FAKELIGHT_ENABLED)
11585 rsurface.lightmaptexture = NULL;
11586 rsurface.deluxemaptexture = NULL;
11587 rsurface.uselightmaptexture = false;
11588 for (;j < endsurface;j++)
11590 surface = rsurface.modelsurfaces + surfacelist[j];
11591 if (texture != surface->texture)
11593 texturesurfacelist[texturenumsurfaces++] = surface;
11598 rsurface.lightmaptexture = surface->lightmaptexture;
11599 rsurface.deluxemaptexture = surface->deluxemaptexture;
11600 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11601 for (;j < endsurface;j++)
11603 surface = rsurface.modelsurfaces + surfacelist[j];
11604 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11606 texturesurfacelist[texturenumsurfaces++] = surface;
11609 // render the range of surfaces
11610 if (ent == r_refdef.scene.worldentity)
11611 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11613 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11615 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11618 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11620 // transparent surfaces get pushed off into the transparent queue
11621 int surfacelistindex;
11622 const msurface_t *surface;
11623 vec3_t tempcenter, center;
11624 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11626 surface = texturesurfacelist[surfacelistindex];
11627 if (r_transparent_sortsurfacesbynearest.integer)
11629 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11630 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11631 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11635 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11636 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11637 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11639 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11640 if (rsurface.entity->transparent_offset) // transparent offset
11642 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11643 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11644 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11646 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);
11650 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11652 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11654 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11656 RSurf_SetupDepthAndCulling();
11657 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11658 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11659 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11663 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11667 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11670 if (!rsurface.texture->currentnumlayers)
11672 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11673 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11675 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11677 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11678 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11679 else if (!rsurface.texture->currentnumlayers)
11681 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11683 // in the deferred case, transparent surfaces were queued during prepass
11684 if (!r_shadow_usingdeferredprepass)
11685 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11689 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11690 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11695 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11698 texture_t *texture;
11699 R_FrameData_SetMark();
11700 // break the surface list down into batches by texture and use of lightmapping
11701 for (i = 0;i < numsurfaces;i = j)
11704 // texture is the base texture pointer, rsurface.texture is the
11705 // current frame/skin the texture is directing us to use (for example
11706 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11707 // use skin 1 instead)
11708 texture = surfacelist[i]->texture;
11709 rsurface.texture = R_GetCurrentTexture(texture);
11710 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11712 // if this texture is not the kind we want, skip ahead to the next one
11713 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11717 if(FAKELIGHT_ENABLED || depthonly || prepass)
11719 rsurface.lightmaptexture = NULL;
11720 rsurface.deluxemaptexture = NULL;
11721 rsurface.uselightmaptexture = false;
11722 // simply scan ahead until we find a different texture or lightmap state
11723 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11728 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11729 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11730 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11731 // simply scan ahead until we find a different texture or lightmap state
11732 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11735 // render the range of surfaces
11736 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11738 R_FrameData_ReturnToMark();
11741 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11745 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11748 if (!rsurface.texture->currentnumlayers)
11750 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11751 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11753 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11755 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11756 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11757 else if (!rsurface.texture->currentnumlayers)
11759 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11761 // in the deferred case, transparent surfaces were queued during prepass
11762 if (!r_shadow_usingdeferredprepass)
11763 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11767 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11768 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11773 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11776 texture_t *texture;
11777 R_FrameData_SetMark();
11778 // break the surface list down into batches by texture and use of lightmapping
11779 for (i = 0;i < numsurfaces;i = j)
11782 // texture is the base texture pointer, rsurface.texture is the
11783 // current frame/skin the texture is directing us to use (for example
11784 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11785 // use skin 1 instead)
11786 texture = surfacelist[i]->texture;
11787 rsurface.texture = R_GetCurrentTexture(texture);
11788 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11790 // if this texture is not the kind we want, skip ahead to the next one
11791 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11795 if(FAKELIGHT_ENABLED || depthonly || prepass)
11797 rsurface.lightmaptexture = NULL;
11798 rsurface.deluxemaptexture = NULL;
11799 rsurface.uselightmaptexture = false;
11800 // simply scan ahead until we find a different texture or lightmap state
11801 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11806 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11807 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11808 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11809 // simply scan ahead until we find a different texture or lightmap state
11810 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11813 // render the range of surfaces
11814 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11816 R_FrameData_ReturnToMark();
11819 float locboxvertex3f[6*4*3] =
11821 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11822 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11823 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11824 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11825 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11826 1,0,0, 0,0,0, 0,1,0, 1,1,0
11829 unsigned short locboxelements[6*2*3] =
11834 12,13,14, 12,14,15,
11835 16,17,18, 16,18,19,
11839 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11842 cl_locnode_t *loc = (cl_locnode_t *)ent;
11844 float vertex3f[6*4*3];
11846 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11847 GL_DepthMask(false);
11848 GL_DepthRange(0, 1);
11849 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11850 GL_DepthTest(true);
11851 GL_CullFace(GL_NONE);
11852 R_EntityMatrix(&identitymatrix);
11854 // R_Mesh_ResetTextureState();
11856 i = surfacelist[0];
11857 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11858 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11859 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11860 surfacelist[0] < 0 ? 0.5f : 0.125f);
11862 if (VectorCompare(loc->mins, loc->maxs))
11864 VectorSet(size, 2, 2, 2);
11865 VectorMA(loc->mins, -0.5f, size, mins);
11869 VectorCopy(loc->mins, mins);
11870 VectorSubtract(loc->maxs, loc->mins, size);
11873 for (i = 0;i < 6*4*3;)
11874 for (j = 0;j < 3;j++, i++)
11875 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11877 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11878 R_SetupShader_Generic_NoTexture(false, false);
11879 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11882 void R_DrawLocs(void)
11885 cl_locnode_t *loc, *nearestloc;
11887 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11888 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11890 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11891 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11895 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11897 if (decalsystem->decals)
11898 Mem_Free(decalsystem->decals);
11899 memset(decalsystem, 0, sizeof(*decalsystem));
11902 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)
11905 tridecal_t *decals;
11908 // expand or initialize the system
11909 if (decalsystem->maxdecals <= decalsystem->numdecals)
11911 decalsystem_t old = *decalsystem;
11912 qboolean useshortelements;
11913 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11914 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11915 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)));
11916 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11917 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11918 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11919 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11920 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11921 if (decalsystem->numdecals)
11922 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11924 Mem_Free(old.decals);
11925 for (i = 0;i < decalsystem->maxdecals*3;i++)
11926 decalsystem->element3i[i] = i;
11927 if (useshortelements)
11928 for (i = 0;i < decalsystem->maxdecals*3;i++)
11929 decalsystem->element3s[i] = i;
11932 // grab a decal and search for another free slot for the next one
11933 decals = decalsystem->decals;
11934 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11935 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11937 decalsystem->freedecal = i;
11938 if (decalsystem->numdecals <= i)
11939 decalsystem->numdecals = i + 1;
11941 // initialize the decal
11943 decal->triangleindex = triangleindex;
11944 decal->surfaceindex = surfaceindex;
11945 decal->decalsequence = decalsequence;
11946 decal->color4f[0][0] = c0[0];
11947 decal->color4f[0][1] = c0[1];
11948 decal->color4f[0][2] = c0[2];
11949 decal->color4f[0][3] = 1;
11950 decal->color4f[1][0] = c1[0];
11951 decal->color4f[1][1] = c1[1];
11952 decal->color4f[1][2] = c1[2];
11953 decal->color4f[1][3] = 1;
11954 decal->color4f[2][0] = c2[0];
11955 decal->color4f[2][1] = c2[1];
11956 decal->color4f[2][2] = c2[2];
11957 decal->color4f[2][3] = 1;
11958 decal->vertex3f[0][0] = v0[0];
11959 decal->vertex3f[0][1] = v0[1];
11960 decal->vertex3f[0][2] = v0[2];
11961 decal->vertex3f[1][0] = v1[0];
11962 decal->vertex3f[1][1] = v1[1];
11963 decal->vertex3f[1][2] = v1[2];
11964 decal->vertex3f[2][0] = v2[0];
11965 decal->vertex3f[2][1] = v2[1];
11966 decal->vertex3f[2][2] = v2[2];
11967 decal->texcoord2f[0][0] = t0[0];
11968 decal->texcoord2f[0][1] = t0[1];
11969 decal->texcoord2f[1][0] = t1[0];
11970 decal->texcoord2f[1][1] = t1[1];
11971 decal->texcoord2f[2][0] = t2[0];
11972 decal->texcoord2f[2][1] = t2[1];
11973 TriangleNormal(v0, v1, v2, decal->plane);
11974 VectorNormalize(decal->plane);
11975 decal->plane[3] = DotProduct(v0, decal->plane);
11978 extern cvar_t cl_decals_bias;
11979 extern cvar_t cl_decals_models;
11980 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11981 // baseparms, parms, temps
11982 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)
11987 const float *vertex3f;
11988 const float *normal3f;
11990 float points[2][9][3];
11997 e = rsurface.modelelement3i + 3*triangleindex;
11999 vertex3f = rsurface.modelvertex3f;
12000 normal3f = rsurface.modelnormal3f;
12004 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12006 index = 3*e[cornerindex];
12007 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
12012 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12014 index = 3*e[cornerindex];
12015 VectorCopy(vertex3f + index, v[cornerindex]);
12020 //TriangleNormal(v[0], v[1], v[2], normal);
12021 //if (DotProduct(normal, localnormal) < 0.0f)
12023 // clip by each of the box planes formed from the projection matrix
12024 // if anything survives, we emit the decal
12025 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]);
12028 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]);
12031 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]);
12034 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]);
12037 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]);
12040 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]);
12043 // some part of the triangle survived, so we have to accept it...
12046 // dynamic always uses the original triangle
12048 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12050 index = 3*e[cornerindex];
12051 VectorCopy(vertex3f + index, v[cornerindex]);
12054 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12056 // convert vertex positions to texcoords
12057 Matrix4x4_Transform(projection, v[cornerindex], temp);
12058 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12059 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12060 // calculate distance fade from the projection origin
12061 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12062 f = bound(0.0f, f, 1.0f);
12063 c[cornerindex][0] = r * f;
12064 c[cornerindex][1] = g * f;
12065 c[cornerindex][2] = b * f;
12066 c[cornerindex][3] = 1.0f;
12067 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12070 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);
12072 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12073 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);
12075 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)
12077 matrix4x4_t projection;
12078 decalsystem_t *decalsystem;
12081 const msurface_t *surface;
12082 const msurface_t *surfaces;
12083 const int *surfacelist;
12084 const texture_t *texture;
12086 int numsurfacelist;
12087 int surfacelistindex;
12090 float localorigin[3];
12091 float localnormal[3];
12092 float localmins[3];
12093 float localmaxs[3];
12096 float planes[6][4];
12099 int bih_triangles_count;
12100 int bih_triangles[256];
12101 int bih_surfaces[256];
12103 decalsystem = &ent->decalsystem;
12104 model = ent->model;
12105 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12107 R_DecalSystem_Reset(&ent->decalsystem);
12111 if (!model->brush.data_leafs && !cl_decals_models.integer)
12113 if (decalsystem->model)
12114 R_DecalSystem_Reset(decalsystem);
12118 if (decalsystem->model != model)
12119 R_DecalSystem_Reset(decalsystem);
12120 decalsystem->model = model;
12122 RSurf_ActiveModelEntity(ent, true, false, false);
12124 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12125 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12126 VectorNormalize(localnormal);
12127 localsize = worldsize*rsurface.inversematrixscale;
12128 localmins[0] = localorigin[0] - localsize;
12129 localmins[1] = localorigin[1] - localsize;
12130 localmins[2] = localorigin[2] - localsize;
12131 localmaxs[0] = localorigin[0] + localsize;
12132 localmaxs[1] = localorigin[1] + localsize;
12133 localmaxs[2] = localorigin[2] + localsize;
12135 //VectorCopy(localnormal, planes[4]);
12136 //VectorVectors(planes[4], planes[2], planes[0]);
12137 AnglesFromVectors(angles, localnormal, NULL, false);
12138 AngleVectors(angles, planes[0], planes[2], planes[4]);
12139 VectorNegate(planes[0], planes[1]);
12140 VectorNegate(planes[2], planes[3]);
12141 VectorNegate(planes[4], planes[5]);
12142 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12143 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12144 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12145 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12146 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12147 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12152 matrix4x4_t forwardprojection;
12153 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12154 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12159 float projectionvector[4][3];
12160 VectorScale(planes[0], ilocalsize, projectionvector[0]);
12161 VectorScale(planes[2], ilocalsize, projectionvector[1]);
12162 VectorScale(planes[4], ilocalsize, projectionvector[2]);
12163 projectionvector[0][0] = planes[0][0] * ilocalsize;
12164 projectionvector[0][1] = planes[1][0] * ilocalsize;
12165 projectionvector[0][2] = planes[2][0] * ilocalsize;
12166 projectionvector[1][0] = planes[0][1] * ilocalsize;
12167 projectionvector[1][1] = planes[1][1] * ilocalsize;
12168 projectionvector[1][2] = planes[2][1] * ilocalsize;
12169 projectionvector[2][0] = planes[0][2] * ilocalsize;
12170 projectionvector[2][1] = planes[1][2] * ilocalsize;
12171 projectionvector[2][2] = planes[2][2] * ilocalsize;
12172 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12173 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12174 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12175 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12179 dynamic = model->surfmesh.isanimated;
12180 numsurfacelist = model->nummodelsurfaces;
12181 surfacelist = model->sortedmodelsurfaces;
12182 surfaces = model->data_surfaces;
12185 bih_triangles_count = -1;
12188 if(model->render_bih.numleafs)
12189 bih = &model->render_bih;
12190 else if(model->collision_bih.numleafs)
12191 bih = &model->collision_bih;
12194 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12195 if(bih_triangles_count == 0)
12197 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12199 if(bih_triangles_count > 0)
12201 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12203 surfaceindex = bih_surfaces[triangleindex];
12204 surface = surfaces + surfaceindex;
12205 texture = surface->texture;
12206 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12208 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12210 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12215 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12217 surfaceindex = surfacelist[surfacelistindex];
12218 surface = surfaces + surfaceindex;
12219 // check cull box first because it rejects more than any other check
12220 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12222 // skip transparent surfaces
12223 texture = surface->texture;
12224 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12226 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12228 numtriangles = surface->num_triangles;
12229 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12230 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12235 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12236 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)
12238 int renderentityindex;
12239 float worldmins[3];
12240 float worldmaxs[3];
12241 entity_render_t *ent;
12243 if (!cl_decals_newsystem.integer)
12246 worldmins[0] = worldorigin[0] - worldsize;
12247 worldmins[1] = worldorigin[1] - worldsize;
12248 worldmins[2] = worldorigin[2] - worldsize;
12249 worldmaxs[0] = worldorigin[0] + worldsize;
12250 worldmaxs[1] = worldorigin[1] + worldsize;
12251 worldmaxs[2] = worldorigin[2] + worldsize;
12253 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12255 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12257 ent = r_refdef.scene.entities[renderentityindex];
12258 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12261 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12265 typedef struct r_decalsystem_splatqueue_s
12267 vec3_t worldorigin;
12268 vec3_t worldnormal;
12272 unsigned int decalsequence;
12274 r_decalsystem_splatqueue_t;
12276 int r_decalsystem_numqueued = 0;
12277 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12279 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)
12281 r_decalsystem_splatqueue_t *queue;
12283 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12286 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12287 VectorCopy(worldorigin, queue->worldorigin);
12288 VectorCopy(worldnormal, queue->worldnormal);
12289 Vector4Set(queue->color, r, g, b, a);
12290 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12291 queue->worldsize = worldsize;
12292 queue->decalsequence = cl.decalsequence++;
12295 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12298 r_decalsystem_splatqueue_t *queue;
12300 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12301 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);
12302 r_decalsystem_numqueued = 0;
12305 extern cvar_t cl_decals_max;
12306 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12309 decalsystem_t *decalsystem = &ent->decalsystem;
12311 unsigned int killsequence;
12316 if (!decalsystem->numdecals)
12319 if (r_showsurfaces.integer)
12322 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12324 R_DecalSystem_Reset(decalsystem);
12328 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12329 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12331 if (decalsystem->lastupdatetime)
12332 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12335 decalsystem->lastupdatetime = r_refdef.scene.time;
12336 numdecals = decalsystem->numdecals;
12338 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12340 if (decal->color4f[0][3])
12342 decal->lived += frametime;
12343 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12345 memset(decal, 0, sizeof(*decal));
12346 if (decalsystem->freedecal > i)
12347 decalsystem->freedecal = i;
12351 decal = decalsystem->decals;
12352 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12355 // collapse the array by shuffling the tail decals into the gaps
12358 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12359 decalsystem->freedecal++;
12360 if (decalsystem->freedecal == numdecals)
12362 decal[decalsystem->freedecal] = decal[--numdecals];
12365 decalsystem->numdecals = numdecals;
12367 if (numdecals <= 0)
12369 // if there are no decals left, reset decalsystem
12370 R_DecalSystem_Reset(decalsystem);
12374 extern skinframe_t *decalskinframe;
12375 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12378 decalsystem_t *decalsystem = &ent->decalsystem;
12387 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12390 numdecals = decalsystem->numdecals;
12394 if (r_showsurfaces.integer)
12397 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12399 R_DecalSystem_Reset(decalsystem);
12403 // if the model is static it doesn't matter what value we give for
12404 // wantnormals and wanttangents, so this logic uses only rules applicable
12405 // to a model, knowing that they are meaningless otherwise
12406 if (ent == r_refdef.scene.worldentity)
12407 RSurf_ActiveWorldEntity();
12409 RSurf_ActiveModelEntity(ent, false, false, false);
12411 decalsystem->lastupdatetime = r_refdef.scene.time;
12413 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12415 // update vertex positions for animated models
12416 v3f = decalsystem->vertex3f;
12417 c4f = decalsystem->color4f;
12418 t2f = decalsystem->texcoord2f;
12419 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12421 if (!decal->color4f[0][3])
12424 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12428 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12431 // update color values for fading decals
12432 if (decal->lived >= cl_decals_time.value)
12433 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12437 c4f[ 0] = decal->color4f[0][0] * alpha;
12438 c4f[ 1] = decal->color4f[0][1] * alpha;
12439 c4f[ 2] = decal->color4f[0][2] * alpha;
12441 c4f[ 4] = decal->color4f[1][0] * alpha;
12442 c4f[ 5] = decal->color4f[1][1] * alpha;
12443 c4f[ 6] = decal->color4f[1][2] * alpha;
12445 c4f[ 8] = decal->color4f[2][0] * alpha;
12446 c4f[ 9] = decal->color4f[2][1] * alpha;
12447 c4f[10] = decal->color4f[2][2] * alpha;
12450 t2f[0] = decal->texcoord2f[0][0];
12451 t2f[1] = decal->texcoord2f[0][1];
12452 t2f[2] = decal->texcoord2f[1][0];
12453 t2f[3] = decal->texcoord2f[1][1];
12454 t2f[4] = decal->texcoord2f[2][0];
12455 t2f[5] = decal->texcoord2f[2][1];
12457 // update vertex positions for animated models
12458 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12460 e = rsurface.modelelement3i + 3*decal->triangleindex;
12461 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12462 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12463 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12467 VectorCopy(decal->vertex3f[0], v3f);
12468 VectorCopy(decal->vertex3f[1], v3f + 3);
12469 VectorCopy(decal->vertex3f[2], v3f + 6);
12472 if (r_refdef.fogenabled)
12474 alpha = RSurf_FogVertex(v3f);
12475 VectorScale(c4f, alpha, c4f);
12476 alpha = RSurf_FogVertex(v3f + 3);
12477 VectorScale(c4f + 4, alpha, c4f + 4);
12478 alpha = RSurf_FogVertex(v3f + 6);
12479 VectorScale(c4f + 8, alpha, c4f + 8);
12490 r_refdef.stats[r_stat_drawndecals] += numtris;
12492 // now render the decals all at once
12493 // (this assumes they all use one particle font texture!)
12494 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);
12495 // R_Mesh_ResetTextureState();
12496 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12497 GL_DepthMask(false);
12498 GL_DepthRange(0, 1);
12499 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12500 GL_DepthTest(true);
12501 GL_CullFace(GL_NONE);
12502 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12503 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12504 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12508 static void R_DrawModelDecals(void)
12512 // fade faster when there are too many decals
12513 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12514 for (i = 0;i < r_refdef.scene.numentities;i++)
12515 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12517 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12518 for (i = 0;i < r_refdef.scene.numentities;i++)
12519 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12520 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12522 R_DecalSystem_ApplySplatEntitiesQueue();
12524 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12525 for (i = 0;i < r_refdef.scene.numentities;i++)
12526 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12528 r_refdef.stats[r_stat_totaldecals] += numdecals;
12530 if (r_showsurfaces.integer)
12533 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12535 for (i = 0;i < r_refdef.scene.numentities;i++)
12537 if (!r_refdef.viewcache.entityvisible[i])
12539 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12540 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12544 extern cvar_t mod_collision_bih;
12545 static void R_DrawDebugModel(void)
12547 entity_render_t *ent = rsurface.entity;
12548 int i, j, flagsmask;
12549 const msurface_t *surface;
12550 dp_model_t *model = ent->model;
12552 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12555 if (r_showoverdraw.value > 0)
12557 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12558 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12559 R_SetupShader_Generic_NoTexture(false, false);
12560 GL_DepthTest(false);
12561 GL_DepthMask(false);
12562 GL_DepthRange(0, 1);
12563 GL_BlendFunc(GL_ONE, GL_ONE);
12564 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12566 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12568 rsurface.texture = R_GetCurrentTexture(surface->texture);
12569 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12571 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12572 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12573 if (!rsurface.texture->currentlayers->depthmask)
12574 GL_Color(c, 0, 0, 1.0f);
12575 else if (ent == r_refdef.scene.worldentity)
12576 GL_Color(c, c, c, 1.0f);
12578 GL_Color(0, c, 0, 1.0f);
12579 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12583 rsurface.texture = NULL;
12586 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12588 // R_Mesh_ResetTextureState();
12589 R_SetupShader_Generic_NoTexture(false, false);
12590 GL_DepthRange(0, 1);
12591 GL_DepthTest(!r_showdisabledepthtest.integer);
12592 GL_DepthMask(false);
12593 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12595 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12599 qboolean cullbox = false;
12600 const q3mbrush_t *brush;
12601 const bih_t *bih = &model->collision_bih;
12602 const bih_leaf_t *bihleaf;
12603 float vertex3f[3][3];
12604 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12605 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12607 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12609 switch (bihleaf->type)
12612 brush = model->brush.data_brushes + bihleaf->itemindex;
12613 if (brush->colbrushf && brush->colbrushf->numtriangles)
12615 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);
12616 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12617 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12620 case BIH_COLLISIONTRIANGLE:
12621 triangleindex = bihleaf->itemindex;
12622 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12623 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12624 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12625 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);
12626 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12627 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12629 case BIH_RENDERTRIANGLE:
12630 triangleindex = bihleaf->itemindex;
12631 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12632 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12633 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12634 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);
12635 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12636 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12642 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12645 if (r_showtris.integer && qglPolygonMode)
12647 if (r_showdisabledepthtest.integer)
12649 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12650 GL_DepthMask(false);
12654 GL_BlendFunc(GL_ONE, GL_ZERO);
12655 GL_DepthMask(true);
12657 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12658 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12660 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12662 rsurface.texture = R_GetCurrentTexture(surface->texture);
12663 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12665 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12666 if (!rsurface.texture->currentlayers->depthmask)
12667 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12668 else if (ent == r_refdef.scene.worldentity)
12669 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12671 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12672 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12676 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12677 rsurface.texture = NULL;
12680 if (r_shownormals.value != 0 && qglBegin)
12684 if (r_showdisabledepthtest.integer)
12686 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12687 GL_DepthMask(false);
12691 GL_BlendFunc(GL_ONE, GL_ZERO);
12692 GL_DepthMask(true);
12694 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12696 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12698 rsurface.texture = R_GetCurrentTexture(surface->texture);
12699 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12701 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12702 qglBegin(GL_LINES);
12703 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12705 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12707 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12708 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12709 qglVertex3f(v[0], v[1], v[2]);
12710 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12711 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12712 qglVertex3f(v[0], v[1], v[2]);
12715 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12717 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12719 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12720 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12721 qglVertex3f(v[0], v[1], v[2]);
12722 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12723 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12724 qglVertex3f(v[0], v[1], v[2]);
12727 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12729 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12731 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12732 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12733 qglVertex3f(v[0], v[1], v[2]);
12734 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12735 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12736 qglVertex3f(v[0], v[1], v[2]);
12739 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12741 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12743 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12744 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12745 qglVertex3f(v[0], v[1], v[2]);
12746 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12747 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12748 qglVertex3f(v[0], v[1], v[2]);
12755 rsurface.texture = NULL;
12760 int r_maxsurfacelist = 0;
12761 const msurface_t **r_surfacelist = NULL;
12762 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12764 int i, j, endj, flagsmask;
12765 dp_model_t *model = r_refdef.scene.worldmodel;
12766 msurface_t *surfaces;
12767 unsigned char *update;
12768 int numsurfacelist = 0;
12772 if (r_maxsurfacelist < model->num_surfaces)
12774 r_maxsurfacelist = model->num_surfaces;
12776 Mem_Free((msurface_t**)r_surfacelist);
12777 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12780 RSurf_ActiveWorldEntity();
12782 surfaces = model->data_surfaces;
12783 update = model->brushq1.lightmapupdateflags;
12785 // update light styles on this submodel
12786 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12788 model_brush_lightstyleinfo_t *style;
12789 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12791 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12793 int *list = style->surfacelist;
12794 style->value = r_refdef.scene.lightstylevalue[style->style];
12795 for (j = 0;j < style->numsurfaces;j++)
12796 update[list[j]] = true;
12801 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12805 R_DrawDebugModel();
12806 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12810 rsurface.lightmaptexture = NULL;
12811 rsurface.deluxemaptexture = NULL;
12812 rsurface.uselightmaptexture = false;
12813 rsurface.texture = NULL;
12814 rsurface.rtlight = NULL;
12815 numsurfacelist = 0;
12816 // add visible surfaces to draw list
12817 for (i = 0;i < model->nummodelsurfaces;i++)
12819 j = model->sortedmodelsurfaces[i];
12820 if (r_refdef.viewcache.world_surfacevisible[j])
12821 r_surfacelist[numsurfacelist++] = surfaces + j;
12823 // update lightmaps if needed
12824 if (model->brushq1.firstrender)
12826 model->brushq1.firstrender = false;
12827 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12829 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12833 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12834 if (r_refdef.viewcache.world_surfacevisible[j])
12836 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12838 // don't do anything if there were no surfaces
12839 if (!numsurfacelist)
12841 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12844 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12846 // add to stats if desired
12847 if (r_speeds.integer && !skysurfaces && !depthonly)
12849 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12850 for (j = 0;j < numsurfacelist;j++)
12851 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12854 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12857 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12859 int i, j, endj, flagsmask;
12860 dp_model_t *model = ent->model;
12861 msurface_t *surfaces;
12862 unsigned char *update;
12863 int numsurfacelist = 0;
12867 if (r_maxsurfacelist < model->num_surfaces)
12869 r_maxsurfacelist = model->num_surfaces;
12871 Mem_Free((msurface_t **)r_surfacelist);
12872 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12875 // if the model is static it doesn't matter what value we give for
12876 // wantnormals and wanttangents, so this logic uses only rules applicable
12877 // to a model, knowing that they are meaningless otherwise
12878 if (ent == r_refdef.scene.worldentity)
12879 RSurf_ActiveWorldEntity();
12880 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12881 RSurf_ActiveModelEntity(ent, false, false, false);
12883 RSurf_ActiveModelEntity(ent, true, true, true);
12884 else if (depthonly)
12886 switch (vid.renderpath)
12888 case RENDERPATH_GL20:
12889 case RENDERPATH_D3D9:
12890 case RENDERPATH_D3D10:
12891 case RENDERPATH_D3D11:
12892 case RENDERPATH_SOFT:
12893 case RENDERPATH_GLES2:
12894 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12896 case RENDERPATH_GL11:
12897 case RENDERPATH_GL13:
12898 case RENDERPATH_GLES1:
12899 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12905 switch (vid.renderpath)
12907 case RENDERPATH_GL20:
12908 case RENDERPATH_D3D9:
12909 case RENDERPATH_D3D10:
12910 case RENDERPATH_D3D11:
12911 case RENDERPATH_SOFT:
12912 case RENDERPATH_GLES2:
12913 RSurf_ActiveModelEntity(ent, true, true, false);
12915 case RENDERPATH_GL11:
12916 case RENDERPATH_GL13:
12917 case RENDERPATH_GLES1:
12918 RSurf_ActiveModelEntity(ent, true, false, false);
12923 surfaces = model->data_surfaces;
12924 update = model->brushq1.lightmapupdateflags;
12926 // update light styles
12927 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12929 model_brush_lightstyleinfo_t *style;
12930 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12932 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12934 int *list = style->surfacelist;
12935 style->value = r_refdef.scene.lightstylevalue[style->style];
12936 for (j = 0;j < style->numsurfaces;j++)
12937 update[list[j]] = true;
12942 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12946 R_DrawDebugModel();
12947 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12951 rsurface.lightmaptexture = NULL;
12952 rsurface.deluxemaptexture = NULL;
12953 rsurface.uselightmaptexture = false;
12954 rsurface.texture = NULL;
12955 rsurface.rtlight = NULL;
12956 numsurfacelist = 0;
12957 // add visible surfaces to draw list
12958 for (i = 0;i < model->nummodelsurfaces;i++)
12959 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12960 // don't do anything if there were no surfaces
12961 if (!numsurfacelist)
12963 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12966 // update lightmaps if needed
12970 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12975 R_BuildLightMap(ent, surfaces + j);
12980 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12982 // add to stats if desired
12983 if (r_speeds.integer && !skysurfaces && !depthonly)
12985 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12986 for (j = 0;j < numsurfacelist;j++)
12987 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12990 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12993 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12995 static texture_t texture;
12996 static msurface_t surface;
12997 const msurface_t *surfacelist = &surface;
12999 // fake enough texture and surface state to render this geometry
13001 texture.update_lastrenderframe = -1; // regenerate this texture
13002 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
13003 texture.basealpha = 1.0f;
13004 texture.currentskinframe = skinframe;
13005 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
13006 texture.offsetmapping = OFFSETMAPPING_OFF;
13007 texture.offsetscale = 1;
13008 texture.specularscalemod = 1;
13009 texture.specularpowermod = 1;
13010 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
13011 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
13012 // JUST GREP FOR "specularscalemod = 1".
13014 surface.texture = &texture;
13015 surface.num_triangles = numtriangles;
13016 surface.num_firsttriangle = firsttriangle;
13017 surface.num_vertices = numvertices;
13018 surface.num_firstvertex = firstvertex;
13021 rsurface.texture = R_GetCurrentTexture(surface.texture);
13022 rsurface.lightmaptexture = NULL;
13023 rsurface.deluxemaptexture = NULL;
13024 rsurface.uselightmaptexture = false;
13025 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
13028 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)
13030 static msurface_t surface;
13031 const msurface_t *surfacelist = &surface;
13033 // fake enough texture and surface state to render this geometry
13034 surface.texture = texture;
13035 surface.num_triangles = numtriangles;
13036 surface.num_firsttriangle = firsttriangle;
13037 surface.num_vertices = numvertices;
13038 surface.num_firstvertex = firstvertex;
13041 rsurface.texture = R_GetCurrentTexture(surface.texture);
13042 rsurface.lightmaptexture = NULL;
13043 rsurface.deluxemaptexture = NULL;
13044 rsurface.uselightmaptexture = false;
13045 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);