2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
97 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
101 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
104 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
105 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 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)"};
115 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)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
118 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"};
119 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
120 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
121 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
123 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
124 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
125 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
127 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"};
128 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
129 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
130 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"};
131 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"};
133 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
134 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
135 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
136 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."};
137 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
138 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
139 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
140 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."};
141 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
142 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
143 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."};
144 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."};
145 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
146 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"};
147 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"};
148 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
149 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
151 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
152 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
153 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"};
154 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
155 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
156 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
157 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
158 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
160 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
161 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
162 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
163 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
164 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
165 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
166 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
167 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
169 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)"};
170 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"};
172 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
173 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
174 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
176 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"};
177 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"};
178 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"};
179 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
180 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
181 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"};
182 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)"};
183 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)"};
184 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
186 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
187 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)"};
188 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
189 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)"};
190 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
191 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)"};
192 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)"};
193 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
194 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"};
195 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."};
196 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
197 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)"};
198 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)"};
199 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)"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
206 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)"};
207 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)"};
208 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
209 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"};
210 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
211 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
212 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
213 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"};
214 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"};
215 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)"};
217 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
218 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
219 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
220 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
222 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
223 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
225 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
226 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
227 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
228 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
229 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
230 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
232 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
233 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
234 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
235 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
236 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
237 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
239 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
240 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
241 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
243 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"};
245 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"};
247 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
249 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
251 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)"};
252 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)"};
253 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
254 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
256 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
257 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"};
259 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."};
261 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)"};
262 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
264 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
265 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
266 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
267 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
270 extern cvar_t v_glslgamma_2d;
272 extern qboolean v_flipped_state;
274 r_framebufferstate_t r_fb;
276 /// shadow volume bsp struct with automatically growing nodes buffer
279 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
281 rtexture_t *r_texture_blanknormalmap;
282 rtexture_t *r_texture_white;
283 rtexture_t *r_texture_grey128;
284 rtexture_t *r_texture_black;
285 rtexture_t *r_texture_notexture;
286 rtexture_t *r_texture_whitecube;
287 rtexture_t *r_texture_normalizationcube;
288 rtexture_t *r_texture_fogattenuation;
289 rtexture_t *r_texture_fogheighttexture;
290 rtexture_t *r_texture_gammaramps;
291 unsigned int r_texture_gammaramps_serial;
292 //rtexture_t *r_texture_fogintensity;
293 rtexture_t *r_texture_reflectcube;
295 // TODO: hash lookups?
296 typedef struct cubemapinfo_s
303 int r_texture_numcubemaps;
304 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
306 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
307 unsigned int r_numqueries;
308 unsigned int r_maxqueries;
310 typedef struct r_qwskincache_s
312 char name[MAX_QPATH];
313 skinframe_t *skinframe;
317 static r_qwskincache_t *r_qwskincache;
318 static int r_qwskincache_size;
320 /// vertex coordinates for a quad that covers the screen exactly
321 extern const float r_screenvertex3f[12];
322 extern const float r_d3dscreenvertex3f[12];
323 const float r_screenvertex3f[12] =
330 const float r_d3dscreenvertex3f[12] =
338 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
341 for (i = 0;i < verts;i++)
352 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
355 for (i = 0;i < verts;i++)
365 // FIXME: move this to client?
368 if (gamemode == GAME_NEHAHRA)
370 Cvar_Set("gl_fogenable", "0");
371 Cvar_Set("gl_fogdensity", "0.2");
372 Cvar_Set("gl_fogred", "0.3");
373 Cvar_Set("gl_foggreen", "0.3");
374 Cvar_Set("gl_fogblue", "0.3");
376 r_refdef.fog_density = 0;
377 r_refdef.fog_red = 0;
378 r_refdef.fog_green = 0;
379 r_refdef.fog_blue = 0;
380 r_refdef.fog_alpha = 1;
381 r_refdef.fog_start = 0;
382 r_refdef.fog_end = 16384;
383 r_refdef.fog_height = 1<<30;
384 r_refdef.fog_fadedepth = 128;
385 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
388 static void R_BuildBlankTextures(void)
390 unsigned char data[4];
391 data[2] = 128; // normal X
392 data[1] = 128; // normal Y
393 data[0] = 255; // normal Z
394 data[3] = 255; // height
395 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
400 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
405 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
410 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
413 static void R_BuildNoTexture(void)
416 unsigned char pix[16][16][4];
417 // this makes a light grey/dark grey checkerboard texture
418 for (y = 0;y < 16;y++)
420 for (x = 0;x < 16;x++)
422 if ((y < 8) ^ (x < 8))
438 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
441 static void R_BuildWhiteCube(void)
443 unsigned char data[6*1*1*4];
444 memset(data, 255, sizeof(data));
445 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
448 static void R_BuildNormalizationCube(void)
452 vec_t s, t, intensity;
455 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
456 for (side = 0;side < 6;side++)
458 for (y = 0;y < NORMSIZE;y++)
460 for (x = 0;x < NORMSIZE;x++)
462 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
463 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
498 intensity = 127.0f / sqrt(DotProduct(v, v));
499 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
500 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
501 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
502 data[((side*64+y)*64+x)*4+3] = 255;
506 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
510 static void R_BuildFogTexture(void)
514 unsigned char data1[FOGWIDTH][4];
515 //unsigned char data2[FOGWIDTH][4];
518 r_refdef.fogmasktable_start = r_refdef.fog_start;
519 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
520 r_refdef.fogmasktable_range = r_refdef.fogrange;
521 r_refdef.fogmasktable_density = r_refdef.fog_density;
523 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
524 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
526 d = (x * r - r_refdef.fogmasktable_start);
527 if(developer_extra.integer)
528 Con_DPrintf("%f ", d);
530 if (r_fog_exp2.integer)
531 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
533 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
534 if(developer_extra.integer)
535 Con_DPrintf(" : %f ", alpha);
536 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
537 if(developer_extra.integer)
538 Con_DPrintf(" = %f\n", alpha);
539 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
542 for (x = 0;x < FOGWIDTH;x++)
544 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
549 //data2[x][0] = 255 - b;
550 //data2[x][1] = 255 - b;
551 //data2[x][2] = 255 - b;
554 if (r_texture_fogattenuation)
556 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
557 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
561 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
562 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
566 static void R_BuildFogHeightTexture(void)
568 unsigned char *inpixels;
576 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
577 if (r_refdef.fogheighttexturename[0])
578 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
581 r_refdef.fog_height_tablesize = 0;
582 if (r_texture_fogheighttexture)
583 R_FreeTexture(r_texture_fogheighttexture);
584 r_texture_fogheighttexture = NULL;
585 if (r_refdef.fog_height_table2d)
586 Mem_Free(r_refdef.fog_height_table2d);
587 r_refdef.fog_height_table2d = NULL;
588 if (r_refdef.fog_height_table1d)
589 Mem_Free(r_refdef.fog_height_table1d);
590 r_refdef.fog_height_table1d = NULL;
594 r_refdef.fog_height_tablesize = size;
595 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
596 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
597 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
599 // LordHavoc: now the magic - what is that table2d for? it is a cooked
600 // average fog color table accounting for every fog layer between a point
601 // and the camera. (Note: attenuation is handled separately!)
602 for (y = 0;y < size;y++)
604 for (x = 0;x < size;x++)
610 for (j = x;j <= y;j++)
612 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
618 for (j = x;j >= y;j--)
620 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
625 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
626 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
627 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
628 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
631 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
634 //=======================================================================================================================================================
636 static const char *builtinshaderstrings[] =
638 #include "shader_glsl.h"
642 const char *builtinhlslshaderstrings[] =
644 #include "shader_hlsl.h"
648 //=======================================================================================================================================================
650 typedef struct shaderpermutationinfo_s
655 shaderpermutationinfo_t;
657 typedef struct shadermodeinfo_s
659 const char *sourcebasename;
660 const char *extension;
661 const char **builtinshaderstrings;
670 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
671 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
673 {"#define USEDIFFUSE\n", " diffuse"},
674 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
675 {"#define USEVIEWTINT\n", " viewtint"},
676 {"#define USECOLORMAPPING\n", " colormapping"},
677 {"#define USESATURATION\n", " saturation"},
678 {"#define USEFOGINSIDE\n", " foginside"},
679 {"#define USEFOGOUTSIDE\n", " fogoutside"},
680 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
681 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
682 {"#define USEGAMMARAMPS\n", " gammaramps"},
683 {"#define USECUBEFILTER\n", " cubefilter"},
684 {"#define USEGLOW\n", " glow"},
685 {"#define USEBLOOM\n", " bloom"},
686 {"#define USESPECULAR\n", " specular"},
687 {"#define USEPOSTPROCESSING\n", " postprocessing"},
688 {"#define USEREFLECTION\n", " reflection"},
689 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
690 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
691 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
692 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
693 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
694 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
695 {"#define USEALPHAKILL\n", " alphakill"},
696 {"#define USEREFLECTCUBE\n", " reflectcube"},
697 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
698 {"#define USEBOUNCEGRID\n", " bouncegrid"},
699 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
700 {"#define USETRIPPY\n", " trippy"},
701 {"#define USEDEPTHRGB\n", " depthrgb"},
702 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
703 {"#define USESKELETAL\n", " skeletal"},
704 {"#define USEOCCLUDE\n", " occlude"}
707 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
708 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
710 // SHADERLANGUAGE_GLSL
712 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
722 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
723 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
724 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
725 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
726 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
727 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730 // SHADERLANGUAGE_HLSL
732 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
741 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
742 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
743 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
744 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
745 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
746 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
747 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
748 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
752 struct r_glsl_permutation_s;
753 typedef struct r_glsl_permutation_s
756 struct r_glsl_permutation_s *hashnext;
758 dpuint64 permutation;
760 /// indicates if we have tried compiling this permutation already
762 /// 0 if compilation failed
764 // texture units assigned to each detected uniform
765 int tex_Texture_First;
766 int tex_Texture_Second;
767 int tex_Texture_GammaRamps;
768 int tex_Texture_Normal;
769 int tex_Texture_Color;
770 int tex_Texture_Gloss;
771 int tex_Texture_Glow;
772 int tex_Texture_SecondaryNormal;
773 int tex_Texture_SecondaryColor;
774 int tex_Texture_SecondaryGloss;
775 int tex_Texture_SecondaryGlow;
776 int tex_Texture_Pants;
777 int tex_Texture_Shirt;
778 int tex_Texture_FogHeightTexture;
779 int tex_Texture_FogMask;
780 int tex_Texture_Lightmap;
781 int tex_Texture_Deluxemap;
782 int tex_Texture_Attenuation;
783 int tex_Texture_Cube;
784 int tex_Texture_Refraction;
785 int tex_Texture_Reflection;
786 int tex_Texture_ShadowMap2D;
787 int tex_Texture_CubeProjection;
788 int tex_Texture_ScreenNormalMap;
789 int tex_Texture_ScreenDiffuse;
790 int tex_Texture_ScreenSpecular;
791 int tex_Texture_ReflectMask;
792 int tex_Texture_ReflectCube;
793 int tex_Texture_BounceGrid;
794 /// locations of detected uniforms in program object, or -1 if not found
795 int loc_Texture_First;
796 int loc_Texture_Second;
797 int loc_Texture_GammaRamps;
798 int loc_Texture_Normal;
799 int loc_Texture_Color;
800 int loc_Texture_Gloss;
801 int loc_Texture_Glow;
802 int loc_Texture_SecondaryNormal;
803 int loc_Texture_SecondaryColor;
804 int loc_Texture_SecondaryGloss;
805 int loc_Texture_SecondaryGlow;
806 int loc_Texture_Pants;
807 int loc_Texture_Shirt;
808 int loc_Texture_FogHeightTexture;
809 int loc_Texture_FogMask;
810 int loc_Texture_Lightmap;
811 int loc_Texture_Deluxemap;
812 int loc_Texture_Attenuation;
813 int loc_Texture_Cube;
814 int loc_Texture_Refraction;
815 int loc_Texture_Reflection;
816 int loc_Texture_ShadowMap2D;
817 int loc_Texture_CubeProjection;
818 int loc_Texture_ScreenNormalMap;
819 int loc_Texture_ScreenDiffuse;
820 int loc_Texture_ScreenSpecular;
821 int loc_Texture_ReflectMask;
822 int loc_Texture_ReflectCube;
823 int loc_Texture_BounceGrid;
825 int loc_BloomBlur_Parameters;
827 int loc_Color_Ambient;
828 int loc_Color_Diffuse;
829 int loc_Color_Specular;
833 int loc_DeferredColor_Ambient;
834 int loc_DeferredColor_Diffuse;
835 int loc_DeferredColor_Specular;
836 int loc_DeferredMod_Diffuse;
837 int loc_DeferredMod_Specular;
838 int loc_DistortScaleRefractReflect;
841 int loc_FogHeightFade;
843 int loc_FogPlaneViewDist;
844 int loc_FogRangeRecip;
847 int loc_LightPosition;
848 int loc_OffsetMapping_ScaleSteps;
849 int loc_OffsetMapping_LodDistance;
850 int loc_OffsetMapping_Bias;
852 int loc_ReflectColor;
853 int loc_ReflectFactor;
854 int loc_ReflectOffset;
855 int loc_RefractColor;
857 int loc_ScreenCenterRefractReflect;
858 int loc_ScreenScaleRefractReflect;
859 int loc_ScreenToDepth;
860 int loc_ShadowMap_Parameters;
861 int loc_ShadowMap_TextureScale;
862 int loc_SpecularPower;
863 int loc_Skeletal_Transform12;
868 int loc_ViewTintColor;
870 int loc_ModelToLight;
872 int loc_BackgroundTexMatrix;
873 int loc_ModelViewProjectionMatrix;
874 int loc_ModelViewMatrix;
875 int loc_PixelToScreenTexCoord;
876 int loc_ModelToReflectCube;
877 int loc_ShadowMapMatrix;
878 int loc_BloomColorSubtract;
879 int loc_NormalmapScrollBlend;
880 int loc_BounceGridMatrix;
881 int loc_BounceGridIntensity;
882 /// uniform block bindings
883 int ubibind_Skeletal_Transform12_UniformBlock;
884 /// uniform block indices
885 int ubiloc_Skeletal_Transform12_UniformBlock;
887 r_glsl_permutation_t;
889 #define SHADERPERMUTATION_HASHSIZE 256
892 // non-degradable "lightweight" shader parameters to keep the permutations simpler
893 // these can NOT degrade! only use for simple stuff
896 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
897 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
898 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
899 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
900 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
901 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
902 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
903 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
904 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
905 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
906 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
907 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
908 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
909 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
911 #define SHADERSTATICPARMS_COUNT 14
913 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
914 static int shaderstaticparms_count = 0;
916 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
917 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
919 extern qboolean r_shadow_shadowmapsampler;
920 extern int r_shadow_shadowmappcf;
921 qboolean R_CompileShader_CheckStaticParms(void)
923 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
924 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
925 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
928 if (r_glsl_saturation_redcompensate.integer)
929 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
930 if (r_glsl_vertextextureblend_usebothalphas.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
932 if (r_shadow_glossexact.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
934 if (r_glsl_postprocess.integer)
936 if (r_glsl_postprocess_uservec1_enable.integer)
937 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
938 if (r_glsl_postprocess_uservec2_enable.integer)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
940 if (r_glsl_postprocess_uservec3_enable.integer)
941 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
942 if (r_glsl_postprocess_uservec4_enable.integer)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
946 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
947 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
948 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
950 if (r_shadow_shadowmapsampler)
951 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
952 if (r_shadow_shadowmappcf > 1)
953 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
954 else if (r_shadow_shadowmappcf)
955 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
956 if (r_celshading.integer)
957 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
958 if (r_celoutlines.integer)
959 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
961 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
964 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
965 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
966 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
968 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
969 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
971 shaderstaticparms_count = 0;
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
980 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
981 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
982 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
983 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
984 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
985 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
986 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
987 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
990 /// information about each possible shader permutation
991 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
992 /// currently selected permutation
993 r_glsl_permutation_t *r_glsl_permutation;
994 /// storage for permutations linked in the hash table
995 memexpandablearray_t r_glsl_permutationarray;
997 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
999 //unsigned int hashdepth = 0;
1000 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1001 r_glsl_permutation_t *p;
1002 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1004 if (p->mode == mode && p->permutation == permutation)
1006 //if (hashdepth > 10)
1007 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1012 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1014 p->permutation = permutation;
1015 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1016 r_glsl_permutationhash[mode][hashindex] = p;
1017 //if (hashdepth > 10)
1018 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1022 static char *R_ShaderStrCat(const char **strings)
1025 const char **p = strings;
1028 for (p = strings;(t = *p);p++)
1031 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1033 for (p = strings;(t = *p);p++)
1043 static char *R_ShaderStrCat(const char **strings);
1044 static void R_InitShaderModeInfo(void)
1047 shadermodeinfo_t *modeinfo;
1048 // 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)
1049 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1051 for (i = 0; i < SHADERMODE_COUNT; i++)
1053 char filename[MAX_QPATH];
1054 modeinfo = &shadermodeinfo[language][i];
1055 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1056 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1057 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1058 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1063 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1066 // if the mode has no filename we have to return the builtin string
1067 if (builtinonly || !modeinfo->filename)
1068 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1069 // note that FS_LoadFile appends a 0 byte to make it a valid string
1070 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1073 if (printfromdisknotice)
1074 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1075 return shaderstring;
1077 // fall back to builtinstring
1078 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1081 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1086 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1088 char permutationname[256];
1089 int vertstrings_count = 0;
1090 int geomstrings_count = 0;
1091 int fragstrings_count = 0;
1092 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1093 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1101 permutationname[0] = 0;
1102 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1104 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1107 if(vid.support.glshaderversion >= 140)
1109 vertstrings_list[vertstrings_count++] = "#version 140\n";
1110 geomstrings_list[geomstrings_count++] = "#version 140\n";
1111 fragstrings_list[fragstrings_count++] = "#version 140\n";
1112 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1113 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1114 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1117 else if(vid.support.glshaderversion >= 130)
1119 vertstrings_list[vertstrings_count++] = "#version 130\n";
1120 geomstrings_list[geomstrings_count++] = "#version 130\n";
1121 fragstrings_list[fragstrings_count++] = "#version 130\n";
1122 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1123 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1124 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126 // if we can do #version 120, we should (this adds the invariant keyword)
1127 else if(vid.support.glshaderversion >= 120)
1129 vertstrings_list[vertstrings_count++] = "#version 120\n";
1130 geomstrings_list[geomstrings_count++] = "#version 120\n";
1131 fragstrings_list[fragstrings_count++] = "#version 120\n";
1132 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1133 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1134 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1136 // GLES also adds several things from GLSL120
1137 switch(vid.renderpath)
1139 case RENDERPATH_GLES2:
1140 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1141 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1142 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1148 // the first pretext is which type of shader to compile as
1149 // (later these will all be bound together as a program object)
1150 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1151 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1152 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1154 // the second pretext is the mode (for example a light source)
1155 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1156 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1157 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1158 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1160 // now add all the permutation pretexts
1161 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1163 if (permutation & (1ll<<i))
1165 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1166 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1167 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1168 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1172 // keep line numbers correct
1173 vertstrings_list[vertstrings_count++] = "\n";
1174 geomstrings_list[geomstrings_count++] = "\n";
1175 fragstrings_list[fragstrings_count++] = "\n";
1180 R_CompileShader_AddStaticParms(mode, permutation);
1181 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1182 vertstrings_count += shaderstaticparms_count;
1183 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184 geomstrings_count += shaderstaticparms_count;
1185 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186 fragstrings_count += shaderstaticparms_count;
1188 // now append the shader text itself
1189 vertstrings_list[vertstrings_count++] = sourcestring;
1190 geomstrings_list[geomstrings_count++] = sourcestring;
1191 fragstrings_list[fragstrings_count++] = sourcestring;
1193 // compile the shader program
1194 if (vertstrings_count + geomstrings_count + fragstrings_count)
1195 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1199 qglUseProgram(p->program);CHECKGLERROR
1200 // look up all the uniform variable names we care about, so we don't
1201 // have to look them up every time we set them
1206 GLint activeuniformindex = 0;
1207 GLint numactiveuniforms = 0;
1208 char uniformname[128];
1209 GLsizei uniformnamelength = 0;
1210 GLint uniformsize = 0;
1211 GLenum uniformtype = 0;
1212 memset(uniformname, 0, sizeof(uniformname));
1213 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1214 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1215 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1217 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1218 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1223 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1224 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1225 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1226 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1227 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1228 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1229 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1230 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1231 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1232 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1233 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1234 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1235 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1236 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1237 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1238 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1239 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1240 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1241 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1242 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1243 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1244 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1245 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1246 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1247 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1248 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1249 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1250 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1251 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1252 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1253 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1254 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1255 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1256 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1257 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1258 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1259 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1260 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1261 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1262 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1263 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1264 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1265 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1266 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1267 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1268 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1269 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1270 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1271 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1272 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1273 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1274 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1275 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1276 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1277 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1278 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1279 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1280 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1281 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1282 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1283 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1284 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1285 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1286 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1287 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1288 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1289 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1290 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1291 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1292 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1293 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1294 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1295 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1296 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1297 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1298 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1299 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1300 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1301 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1302 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1303 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1304 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1305 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1306 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1307 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1308 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1309 // initialize the samplers to refer to the texture units we use
1310 p->tex_Texture_First = -1;
1311 p->tex_Texture_Second = -1;
1312 p->tex_Texture_GammaRamps = -1;
1313 p->tex_Texture_Normal = -1;
1314 p->tex_Texture_Color = -1;
1315 p->tex_Texture_Gloss = -1;
1316 p->tex_Texture_Glow = -1;
1317 p->tex_Texture_SecondaryNormal = -1;
1318 p->tex_Texture_SecondaryColor = -1;
1319 p->tex_Texture_SecondaryGloss = -1;
1320 p->tex_Texture_SecondaryGlow = -1;
1321 p->tex_Texture_Pants = -1;
1322 p->tex_Texture_Shirt = -1;
1323 p->tex_Texture_FogHeightTexture = -1;
1324 p->tex_Texture_FogMask = -1;
1325 p->tex_Texture_Lightmap = -1;
1326 p->tex_Texture_Deluxemap = -1;
1327 p->tex_Texture_Attenuation = -1;
1328 p->tex_Texture_Cube = -1;
1329 p->tex_Texture_Refraction = -1;
1330 p->tex_Texture_Reflection = -1;
1331 p->tex_Texture_ShadowMap2D = -1;
1332 p->tex_Texture_CubeProjection = -1;
1333 p->tex_Texture_ScreenNormalMap = -1;
1334 p->tex_Texture_ScreenDiffuse = -1;
1335 p->tex_Texture_ScreenSpecular = -1;
1336 p->tex_Texture_ReflectMask = -1;
1337 p->tex_Texture_ReflectCube = -1;
1338 p->tex_Texture_BounceGrid = -1;
1339 // bind the texture samplers in use
1341 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1342 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1343 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1344 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1345 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1346 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1347 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1348 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1349 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1350 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1351 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1352 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1353 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1354 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1355 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1356 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1357 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1358 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1359 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1360 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1361 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1362 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1363 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1364 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1365 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1366 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1367 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1368 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1369 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1370 // get the uniform block indices so we can bind them
1371 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1372 if (vid.support.arb_uniform_buffer_object)
1373 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1376 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1377 // clear the uniform block bindings
1378 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1379 // bind the uniform blocks in use
1381 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1382 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1384 // we're done compiling and setting up the shader, at least until it is used
1386 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1389 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1393 Mem_Free(sourcestring);
1396 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1398 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1399 if (r_glsl_permutation != perm)
1401 r_glsl_permutation = perm;
1402 if (!r_glsl_permutation->program)
1404 if (!r_glsl_permutation->compiled)
1406 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1407 R_GLSL_CompilePermutation(perm, mode, permutation);
1409 if (!r_glsl_permutation->program)
1411 // remove features until we find a valid permutation
1413 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1415 // reduce i more quickly whenever it would not remove any bits
1416 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1417 if (!(permutation & j))
1420 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1421 if (!r_glsl_permutation->compiled)
1422 R_GLSL_CompilePermutation(perm, mode, permutation);
1423 if (r_glsl_permutation->program)
1426 if (i >= SHADERPERMUTATION_COUNT)
1428 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1429 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1430 qglUseProgram(0);CHECKGLERROR
1431 return; // no bit left to clear, entire mode is broken
1436 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1438 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1439 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1440 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1448 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1449 extern D3DCAPS9 vid_d3d9caps;
1452 struct r_hlsl_permutation_s;
1453 typedef struct r_hlsl_permutation_s
1455 /// hash lookup data
1456 struct r_hlsl_permutation_s *hashnext;
1458 dpuint64 permutation;
1460 /// indicates if we have tried compiling this permutation already
1462 /// NULL if compilation failed
1463 IDirect3DVertexShader9 *vertexshader;
1464 IDirect3DPixelShader9 *pixelshader;
1466 r_hlsl_permutation_t;
1468 typedef enum D3DVSREGISTER_e
1470 D3DVSREGISTER_TexMatrix = 0, // float4x4
1471 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1472 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1473 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1474 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1475 D3DVSREGISTER_ModelToLight = 20, // float4x4
1476 D3DVSREGISTER_EyePosition = 24,
1477 D3DVSREGISTER_FogPlane = 25,
1478 D3DVSREGISTER_LightDir = 26,
1479 D3DVSREGISTER_LightPosition = 27,
1483 typedef enum D3DPSREGISTER_e
1485 D3DPSREGISTER_Alpha = 0,
1486 D3DPSREGISTER_BloomBlur_Parameters = 1,
1487 D3DPSREGISTER_ClientTime = 2,
1488 D3DPSREGISTER_Color_Ambient = 3,
1489 D3DPSREGISTER_Color_Diffuse = 4,
1490 D3DPSREGISTER_Color_Specular = 5,
1491 D3DPSREGISTER_Color_Glow = 6,
1492 D3DPSREGISTER_Color_Pants = 7,
1493 D3DPSREGISTER_Color_Shirt = 8,
1494 D3DPSREGISTER_DeferredColor_Ambient = 9,
1495 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1496 D3DPSREGISTER_DeferredColor_Specular = 11,
1497 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1498 D3DPSREGISTER_DeferredMod_Specular = 13,
1499 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1500 D3DPSREGISTER_EyePosition = 15, // unused
1501 D3DPSREGISTER_FogColor = 16,
1502 D3DPSREGISTER_FogHeightFade = 17,
1503 D3DPSREGISTER_FogPlane = 18,
1504 D3DPSREGISTER_FogPlaneViewDist = 19,
1505 D3DPSREGISTER_FogRangeRecip = 20,
1506 D3DPSREGISTER_LightColor = 21,
1507 D3DPSREGISTER_LightDir = 22, // unused
1508 D3DPSREGISTER_LightPosition = 23,
1509 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1510 D3DPSREGISTER_PixelSize = 25,
1511 D3DPSREGISTER_ReflectColor = 26,
1512 D3DPSREGISTER_ReflectFactor = 27,
1513 D3DPSREGISTER_ReflectOffset = 28,
1514 D3DPSREGISTER_RefractColor = 29,
1515 D3DPSREGISTER_Saturation = 30,
1516 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1517 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1518 D3DPSREGISTER_ScreenToDepth = 33,
1519 D3DPSREGISTER_ShadowMap_Parameters = 34,
1520 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1521 D3DPSREGISTER_SpecularPower = 36,
1522 D3DPSREGISTER_UserVec1 = 37,
1523 D3DPSREGISTER_UserVec2 = 38,
1524 D3DPSREGISTER_UserVec3 = 39,
1525 D3DPSREGISTER_UserVec4 = 40,
1526 D3DPSREGISTER_ViewTintColor = 41,
1527 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1528 D3DPSREGISTER_BloomColorSubtract = 43,
1529 D3DPSREGISTER_ViewToLight = 44, // float4x4
1530 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1531 D3DPSREGISTER_NormalmapScrollBlend = 52,
1532 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1533 D3DPSREGISTER_OffsetMapping_Bias = 54,
1538 /// information about each possible shader permutation
1539 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1540 /// currently selected permutation
1541 r_hlsl_permutation_t *r_hlsl_permutation;
1542 /// storage for permutations linked in the hash table
1543 memexpandablearray_t r_hlsl_permutationarray;
1545 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1547 //unsigned int hashdepth = 0;
1548 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1549 r_hlsl_permutation_t *p;
1550 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1552 if (p->mode == mode && p->permutation == permutation)
1554 //if (hashdepth > 10)
1555 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1560 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1562 p->permutation = permutation;
1563 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1564 r_hlsl_permutationhash[mode][hashindex] = p;
1565 //if (hashdepth > 10)
1566 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1571 //#include <d3dx9shader.h>
1572 //#include <d3dx9mesh.h>
1574 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1576 DWORD *vsbin = NULL;
1577 DWORD *psbin = NULL;
1578 fs_offset_t vsbinsize;
1579 fs_offset_t psbinsize;
1580 // IDirect3DVertexShader9 *vs = NULL;
1581 // IDirect3DPixelShader9 *ps = NULL;
1582 ID3DXBuffer *vslog = NULL;
1583 ID3DXBuffer *vsbuffer = NULL;
1584 ID3DXConstantTable *vsconstanttable = NULL;
1585 ID3DXBuffer *pslog = NULL;
1586 ID3DXBuffer *psbuffer = NULL;
1587 ID3DXConstantTable *psconstanttable = NULL;
1590 char temp[MAX_INPUTLINE];
1591 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1593 qboolean debugshader = gl_paranoid.integer != 0;
1594 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1595 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1598 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1599 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1601 if ((!vsbin && vertstring) || (!psbin && fragstring))
1603 const char* dllnames_d3dx9 [] =
1627 dllhandle_t d3dx9_dll = NULL;
1628 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1629 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1630 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631 dllfunction_t d3dx9_dllfuncs[] =
1633 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1634 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1635 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1638 // 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...
1639 #ifndef ID3DXBuffer_GetBufferPointer
1640 #if !defined(__cplusplus) || defined(CINTERFACE)
1641 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1642 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1643 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1645 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1646 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1647 #define ID3DXBuffer_Release(p) (p)->Release()
1650 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1652 DWORD shaderflags = 0;
1654 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1655 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1656 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1657 if (vertstring && vertstring[0])
1661 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1662 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1665 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1668 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1669 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1670 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1671 ID3DXBuffer_Release(vsbuffer);
1675 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1676 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1677 ID3DXBuffer_Release(vslog);
1680 if (fragstring && fragstring[0])
1684 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1685 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1688 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1691 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1692 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1693 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1694 ID3DXBuffer_Release(psbuffer);
1698 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1699 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1700 ID3DXBuffer_Release(pslog);
1703 Sys_UnloadLibrary(&d3dx9_dll);
1706 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1710 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1711 if (FAILED(vsresult))
1712 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1713 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1714 if (FAILED(psresult))
1715 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1717 // free the shader data
1718 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1719 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1722 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1725 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1726 int vertstring_length = 0;
1727 int geomstring_length = 0;
1728 int fragstring_length = 0;
1731 char *vertstring, *geomstring, *fragstring;
1732 char permutationname[256];
1733 char cachename[256];
1734 int vertstrings_count = 0;
1735 int geomstrings_count = 0;
1736 int fragstrings_count = 0;
1737 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1738 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1739 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1744 p->vertexshader = NULL;
1745 p->pixelshader = NULL;
1747 permutationname[0] = 0;
1749 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1751 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1752 strlcat(cachename, "hlsl/", sizeof(cachename));
1754 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1755 vertstrings_count = 0;
1756 geomstrings_count = 0;
1757 fragstrings_count = 0;
1758 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1759 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1760 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1762 // the first pretext is which type of shader to compile as
1763 // (later these will all be bound together as a program object)
1764 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1765 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1766 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1768 // the second pretext is the mode (for example a light source)
1769 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1770 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1771 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1772 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1773 strlcat(cachename, modeinfo->name, sizeof(cachename));
1775 // now add all the permutation pretexts
1776 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778 if (permutation & (1ll<<i))
1780 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1781 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1782 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1783 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1784 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1788 // keep line numbers correct
1789 vertstrings_list[vertstrings_count++] = "\n";
1790 geomstrings_list[geomstrings_count++] = "\n";
1791 fragstrings_list[fragstrings_count++] = "\n";
1796 R_CompileShader_AddStaticParms(mode, permutation);
1797 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1798 vertstrings_count += shaderstaticparms_count;
1799 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800 geomstrings_count += shaderstaticparms_count;
1801 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802 fragstrings_count += shaderstaticparms_count;
1804 // replace spaces in the cachename with _ characters
1805 for (i = 0;cachename[i];i++)
1806 if (cachename[i] == ' ')
1809 // now append the shader text itself
1810 vertstrings_list[vertstrings_count++] = sourcestring;
1811 geomstrings_list[geomstrings_count++] = sourcestring;
1812 fragstrings_list[fragstrings_count++] = sourcestring;
1814 vertstring_length = 0;
1815 for (i = 0;i < vertstrings_count;i++)
1816 vertstring_length += (int)strlen(vertstrings_list[i]);
1817 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1818 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1819 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1821 geomstring_length = 0;
1822 for (i = 0;i < geomstrings_count;i++)
1823 geomstring_length += (int)strlen(geomstrings_list[i]);
1824 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1825 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1826 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1828 fragstring_length = 0;
1829 for (i = 0;i < fragstrings_count;i++)
1830 fragstring_length += (int)strlen(fragstrings_list[i]);
1831 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1832 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1833 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1835 // try to load the cached shader, or generate one
1836 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1838 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1839 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1841 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1845 Mem_Free(vertstring);
1847 Mem_Free(geomstring);
1849 Mem_Free(fragstring);
1851 Mem_Free(sourcestring);
1854 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1855 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1856 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);}
1857 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);}
1858 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);}
1859 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);}
1861 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1862 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1863 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);}
1864 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);}
1865 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);}
1866 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);}
1868 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1870 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1871 if (r_hlsl_permutation != perm)
1873 r_hlsl_permutation = perm;
1874 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1876 if (!r_hlsl_permutation->compiled)
1877 R_HLSL_CompilePermutation(perm, mode, permutation);
1878 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1880 // remove features until we find a valid permutation
1882 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1884 // reduce i more quickly whenever it would not remove any bits
1885 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1886 if (!(permutation & j))
1889 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1890 if (!r_hlsl_permutation->compiled)
1891 R_HLSL_CompilePermutation(perm, mode, permutation);
1892 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1895 if (i >= SHADERPERMUTATION_COUNT)
1897 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1898 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1899 return; // no bit left to clear, entire mode is broken
1903 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1904 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1906 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1907 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1908 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1912 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1914 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1915 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1916 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1917 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1920 void R_GLSL_Restart_f(void)
1922 unsigned int i, limit;
1923 switch(vid.renderpath)
1925 case RENDERPATH_D3D9:
1928 r_hlsl_permutation_t *p;
1929 r_hlsl_permutation = NULL;
1930 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1931 for (i = 0;i < limit;i++)
1933 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1935 if (p->vertexshader)
1936 IDirect3DVertexShader9_Release(p->vertexshader);
1938 IDirect3DPixelShader9_Release(p->pixelshader);
1939 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1942 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1946 case RENDERPATH_D3D10:
1947 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1949 case RENDERPATH_D3D11:
1950 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952 case RENDERPATH_GL20:
1953 case RENDERPATH_GLES2:
1955 r_glsl_permutation_t *p;
1956 r_glsl_permutation = NULL;
1957 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1958 for (i = 0;i < limit;i++)
1960 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1962 GL_Backend_FreeProgram(p->program);
1963 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1966 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1969 case RENDERPATH_GL11:
1970 case RENDERPATH_GL13:
1971 case RENDERPATH_GLES1:
1973 case RENDERPATH_SOFT:
1978 static void R_GLSL_DumpShader_f(void)
1980 int i, language, mode, dupe;
1982 shadermodeinfo_t *modeinfo;
1985 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1987 modeinfo = shadermodeinfo[language];
1988 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1990 // don't dump the same file multiple times (most or all shaders come from the same file)
1991 for (dupe = mode - 1;dupe >= 0;dupe--)
1992 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1996 text = modeinfo[mode].builtinstring;
1999 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2002 FS_Print(file, "/* The engine may define the following macros:\n");
2003 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2004 for (i = 0;i < SHADERMODE_COUNT;i++)
2005 FS_Print(file, modeinfo[i].pretext);
2006 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2007 FS_Print(file, shaderpermutationinfo[i].pretext);
2008 FS_Print(file, "*/\n");
2009 FS_Print(file, text);
2011 Con_Printf("%s written\n", modeinfo[mode].filename);
2014 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2019 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2021 dpuint64 permutation = 0;
2022 if (r_trippy.integer && !notrippy)
2023 permutation |= SHADERPERMUTATION_TRIPPY;
2024 permutation |= SHADERPERMUTATION_VIEWTINT;
2026 permutation |= SHADERPERMUTATION_DIFFUSE;
2028 permutation |= SHADERPERMUTATION_SPECULAR;
2029 if (texturemode == GL_MODULATE)
2030 permutation |= SHADERPERMUTATION_COLORMAPPING;
2031 else if (texturemode == GL_ADD)
2032 permutation |= SHADERPERMUTATION_GLOW;
2033 else if (texturemode == GL_DECAL)
2034 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2035 if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2036 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2037 if (suppresstexalpha)
2038 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2040 texturemode = GL_MODULATE;
2041 if (vid.allowalphatocoverage)
2042 GL_AlphaToCoverage(false);
2043 switch (vid.renderpath)
2045 case RENDERPATH_D3D9:
2047 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2048 R_Mesh_TexBind(GL20TU_FIRST , first );
2049 R_Mesh_TexBind(GL20TU_SECOND, second);
2050 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2051 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2054 case RENDERPATH_D3D10:
2055 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2057 case RENDERPATH_D3D11:
2058 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2060 case RENDERPATH_GL20:
2061 case RENDERPATH_GLES2:
2062 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2063 if (r_glsl_permutation->tex_Texture_First >= 0)
2064 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2065 if (r_glsl_permutation->tex_Texture_Second >= 0)
2066 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2067 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2068 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2070 case RENDERPATH_GL13:
2071 case RENDERPATH_GLES1:
2072 R_Mesh_TexBind(0, first );
2073 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2074 R_Mesh_TexMatrix(0, NULL);
2075 R_Mesh_TexBind(1, second);
2078 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2079 R_Mesh_TexMatrix(1, NULL);
2082 case RENDERPATH_GL11:
2083 R_Mesh_TexBind(0, first );
2084 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2085 R_Mesh_TexMatrix(0, NULL);
2087 case RENDERPATH_SOFT:
2088 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2089 R_Mesh_TexBind(GL20TU_FIRST , first );
2090 R_Mesh_TexBind(GL20TU_SECOND, second);
2095 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2097 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2100 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2102 dpuint64 permutation = 0;
2103 if (r_trippy.integer && !notrippy)
2104 permutation |= SHADERPERMUTATION_TRIPPY;
2106 permutation |= SHADERPERMUTATION_DEPTHRGB;
2108 permutation |= SHADERPERMUTATION_SKELETAL;
2110 if (vid.allowalphatocoverage)
2111 GL_AlphaToCoverage(false);
2112 switch (vid.renderpath)
2114 case RENDERPATH_D3D9:
2116 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2119 case RENDERPATH_D3D10:
2120 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2122 case RENDERPATH_D3D11:
2123 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2125 case RENDERPATH_GL20:
2126 case RENDERPATH_GLES2:
2127 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2128 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2129 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);
2132 case RENDERPATH_GL13:
2133 case RENDERPATH_GLES1:
2134 R_Mesh_TexBind(0, 0);
2135 R_Mesh_TexBind(1, 0);
2137 case RENDERPATH_GL11:
2138 R_Mesh_TexBind(0, 0);
2140 case RENDERPATH_SOFT:
2141 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2146 extern qboolean r_shadow_usingdeferredprepass;
2147 extern rtexture_t *r_shadow_attenuationgradienttexture;
2148 extern rtexture_t *r_shadow_attenuation2dtexture;
2149 extern rtexture_t *r_shadow_attenuation3dtexture;
2150 extern qboolean r_shadow_usingshadowmap2d;
2151 extern qboolean r_shadow_usingshadowmaportho;
2152 extern float r_shadow_modelshadowmap_texturescale[4];
2153 extern float r_shadow_modelshadowmap_parameters[4];
2154 extern float r_shadow_lightshadowmap_texturescale[4];
2155 extern float r_shadow_lightshadowmap_parameters[4];
2156 extern qboolean r_shadow_shadowmapvsdct;
2157 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2158 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2159 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2160 extern matrix4x4_t r_shadow_shadowmapmatrix;
2161 extern int r_shadow_prepass_width;
2162 extern int r_shadow_prepass_height;
2163 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2164 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2165 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2166 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2168 #define BLENDFUNC_ALLOWS_COLORMOD 1
2169 #define BLENDFUNC_ALLOWS_FOG 2
2170 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2171 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2172 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2173 static int R_BlendFuncFlags(int src, int dst)
2177 // a blendfunc allows colormod if:
2178 // a) it can never keep the destination pixel invariant, or
2179 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2180 // this is to prevent unintended side effects from colormod
2182 // a blendfunc allows fog if:
2183 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2184 // this is to prevent unintended side effects from fog
2186 // these checks are the output of fogeval.pl
2188 r |= BLENDFUNC_ALLOWS_COLORMOD;
2189 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2190 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2191 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2193 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2195 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2197 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2198 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2199 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2200 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2201 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2202 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2204 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2205 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2206 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2207 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2208 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2209 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2214 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2216 // select a permutation of the lighting shader appropriate to this
2217 // combination of texture, entity, light source, and fogging, only use the
2218 // minimum features necessary to avoid wasting rendering time in the
2219 // fragment shader on features that are not being used
2220 dpuint64 permutation = 0;
2221 unsigned int mode = 0;
2223 texture_t *t = rsurface.texture;
2225 matrix4x4_t tempmatrix;
2226 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2227 if (r_trippy.integer && !notrippy)
2228 permutation |= SHADERPERMUTATION_TRIPPY;
2229 if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2230 permutation |= SHADERPERMUTATION_ALPHAKILL;
2231 if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2232 permutation |= SHADERPERMUTATION_OCCLUDE;
2233 if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2234 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2235 if (rsurfacepass == RSURFPASS_BACKGROUND)
2237 // distorted background
2238 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2240 mode = SHADERMODE_WATER;
2241 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2242 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2243 if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2245 // this is the right thing to do for wateralpha
2246 GL_BlendFunc(GL_ONE, GL_ZERO);
2247 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2251 // this is the right thing to do for entity alpha
2252 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2253 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2258 mode = SHADERMODE_REFRACTION;
2259 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2260 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2261 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2262 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2266 mode = SHADERMODE_GENERIC;
2267 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2268 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2269 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271 if (vid.allowalphatocoverage)
2272 GL_AlphaToCoverage(false);
2274 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2276 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2278 switch(t->offsetmapping)
2280 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2281 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2282 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2283 case OFFSETMAPPING_OFF: break;
2286 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2287 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2288 // normalmap (deferred prepass), may use alpha test on diffuse
2289 mode = SHADERMODE_DEFERREDGEOMETRY;
2290 GL_BlendFunc(GL_ONE, GL_ZERO);
2291 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2292 if (vid.allowalphatocoverage)
2293 GL_AlphaToCoverage(false);
2295 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2297 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2299 switch(t->offsetmapping)
2301 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304 case OFFSETMAPPING_OFF: break;
2307 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2310 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2312 mode = SHADERMODE_LIGHTSOURCE;
2313 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2314 permutation |= SHADERPERMUTATION_CUBEFILTER;
2315 if (VectorLength2(rtlightdiffuse) > 0)
2316 permutation |= SHADERPERMUTATION_DIFFUSE;
2317 if (VectorLength2(rtlightspecular) > 0)
2318 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2319 if (r_refdef.fogenabled)
2320 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2321 if (t->colormapping)
2322 permutation |= SHADERPERMUTATION_COLORMAPPING;
2323 if (r_shadow_usingshadowmap2d)
2325 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2326 if(r_shadow_shadowmapvsdct)
2327 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2329 if (r_shadow_shadowmap2ddepthbuffer)
2330 permutation |= SHADERPERMUTATION_DEPTHRGB;
2332 if (t->reflectmasktexture)
2333 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2335 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2336 if (vid.allowalphatocoverage)
2337 GL_AlphaToCoverage(false);
2339 else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2341 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2343 switch(t->offsetmapping)
2345 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2346 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348 case OFFSETMAPPING_OFF: break;
2351 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2352 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2354 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2355 // directional model lighting
2356 mode = SHADERMODE_LIGHTDIRECTION;
2357 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358 permutation |= SHADERPERMUTATION_GLOW;
2359 if (VectorLength2(t->render_modellight_diffuse))
2360 permutation |= SHADERPERMUTATION_DIFFUSE;
2361 if (VectorLength2(t->render_modellight_specular) > 0)
2362 permutation |= SHADERPERMUTATION_SPECULAR;
2363 if (r_refdef.fogenabled)
2364 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365 if (t->colormapping)
2366 permutation |= SHADERPERMUTATION_COLORMAPPING;
2367 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2369 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2372 if (r_shadow_shadowmap2ddepthbuffer)
2373 permutation |= SHADERPERMUTATION_DEPTHRGB;
2375 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376 permutation |= SHADERPERMUTATION_REFLECTION;
2377 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2378 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379 if (t->reflectmasktexture)
2380 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2383 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384 if (r_shadow_bouncegrid_state.directional)
2385 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2387 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2388 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2389 // when using alphatocoverage, we don't need alphakill
2390 if (vid.allowalphatocoverage)
2392 if (r_transparent_alphatocoverage.integer)
2394 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2398 GL_AlphaToCoverage(false);
2403 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2405 switch(t->offsetmapping)
2407 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410 case OFFSETMAPPING_OFF: break;
2413 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2416 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2418 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419 permutation |= SHADERPERMUTATION_GLOW;
2420 if (r_refdef.fogenabled)
2421 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422 if (t->colormapping)
2423 permutation |= SHADERPERMUTATION_COLORMAPPING;
2424 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2426 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2429 if (r_shadow_shadowmap2ddepthbuffer)
2430 permutation |= SHADERPERMUTATION_DEPTHRGB;
2432 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433 permutation |= SHADERPERMUTATION_REFLECTION;
2434 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2435 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436 if (t->reflectmasktexture)
2437 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438 if (FAKELIGHT_ENABLED)
2440 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2441 mode = SHADERMODE_FAKELIGHT;
2442 permutation |= SHADERPERMUTATION_DIFFUSE;
2443 if (VectorLength2(t->render_lightmap_specular) > 0)
2444 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448 // deluxemapping (light direction texture)
2449 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453 permutation |= SHADERPERMUTATION_DIFFUSE;
2454 if (VectorLength2(t->render_lightmap_specular) > 0)
2455 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457 else if (r_glsl_deluxemapping.integer >= 2)
2459 // fake deluxemapping (uniform light direction in tangentspace)
2460 if (rsurface.uselightmaptexture)
2461 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2463 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464 permutation |= SHADERPERMUTATION_DIFFUSE;
2465 if (VectorLength2(t->render_lightmap_specular) > 0)
2466 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468 else if (rsurface.uselightmaptexture)
2470 // ordinary lightmapping (q1bsp, q3bsp)
2471 mode = SHADERMODE_LIGHTMAP;
2475 // ordinary vertex coloring (q3bsp)
2476 mode = SHADERMODE_VERTEXCOLOR;
2478 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2480 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481 if (r_shadow_bouncegrid_state.directional)
2482 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2485 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2486 // when using alphatocoverage, we don't need alphakill
2487 if (vid.allowalphatocoverage)
2489 if (r_transparent_alphatocoverage.integer)
2491 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2495 GL_AlphaToCoverage(false);
2498 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502 switch(vid.renderpath)
2504 case RENDERPATH_D3D9:
2506 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);
2507 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2508 R_SetupShader_SetPermutationHLSL(mode, permutation);
2509 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510 if (mode == SHADERMODE_LIGHTSOURCE)
2512 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2517 if (mode == SHADERMODE_LIGHTDIRECTION)
2519 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2522 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2528 if (mode == SHADERMODE_LIGHTSOURCE)
2530 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2532 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2533 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2534 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2536 // additive passes are only darkened by fog, not tinted
2537 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2542 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2543 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2544 if (mode == SHADERMODE_FLATCOLOR)
2546 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2548 else if (mode == SHADERMODE_LIGHTDIRECTION)
2550 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2551 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2553 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2554 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2558 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2559 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2560 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2562 // additive passes are only darkened by fog, not tinted
2563 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2564 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2567 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2568 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2569 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2570 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2571 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2572 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2573 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2574 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2575 if (mode == SHADERMODE_WATER)
2576 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2578 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2580 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2581 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2585 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2586 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2588 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2589 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2590 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2591 if (t->pantstexture)
2592 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2594 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2595 if (t->shirttexture)
2596 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2598 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2599 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2600 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2601 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2602 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2603 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2604 r_glsl_offsetmapping_scale.value*t->offsetscale,
2605 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2606 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2607 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2609 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2610 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2611 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2612 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2614 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2615 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2616 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2617 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2618 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2619 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2620 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2621 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2622 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2623 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2624 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2625 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2626 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2627 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2628 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2629 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2630 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2631 if (rsurfacepass == RSURFPASS_BACKGROUND)
2633 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2634 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2635 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2639 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2642 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2643 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2644 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2646 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2647 if (rsurface.rtlight)
2649 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2650 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2655 case RENDERPATH_D3D10:
2656 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2658 case RENDERPATH_D3D11:
2659 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2661 case RENDERPATH_GL20:
2662 case RENDERPATH_GLES2:
2663 if (!vid.useinterleavedarrays)
2665 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);
2666 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2667 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2668 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2669 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2670 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2671 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2672 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2673 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2674 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2675 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2679 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);
2680 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2682 // this has to be after RSurf_PrepareVerticesForBatch
2683 if (rsurface.batchskeletaltransform3x4buffer)
2684 permutation |= SHADERPERMUTATION_SKELETAL;
2685 R_SetupShader_SetPermutationGLSL(mode, permutation);
2686 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2687 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);
2689 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2690 if (mode == SHADERMODE_LIGHTSOURCE)
2692 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2693 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2694 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2695 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2696 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2697 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2699 // additive passes are only darkened by fog, not tinted
2700 if (r_glsl_permutation->loc_FogColor >= 0)
2701 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2702 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2706 if (mode == SHADERMODE_FLATCOLOR)
2708 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2710 else if (mode == SHADERMODE_LIGHTDIRECTION)
2712 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2713 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2714 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2715 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2716 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2717 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2718 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2722 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2723 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2724 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2725 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2726 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2728 // additive passes are only darkened by fog, not tinted
2729 if (r_glsl_permutation->loc_FogColor >= 0)
2731 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2732 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2734 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2736 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2737 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]);
2738 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]);
2739 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2740 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2741 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2742 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2743 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2744 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2746 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2747 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2748 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2749 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2751 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]);
2752 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]);
2756 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]);
2757 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]);
2760 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2761 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2762 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2763 if (r_glsl_permutation->loc_Color_Pants >= 0)
2765 if (t->pantstexture)
2766 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2768 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2770 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2772 if (t->shirttexture)
2773 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2775 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2777 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]);
2778 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2779 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2780 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2781 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2782 r_glsl_offsetmapping_scale.value*t->offsetscale,
2783 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2784 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2785 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2787 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);
2788 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2789 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]);
2790 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2791 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);}
2792 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2794 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2795 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2796 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2797 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , t->nmaptexture );
2798 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , t->basetexture );
2799 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , t->glosstexture );
2800 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , t->glowtexture );
2801 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , t->backgroundnmaptexture );
2802 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , t->backgroundbasetexture );
2803 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , t->backgroundglosstexture );
2804 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , t->backgroundglowtexture );
2805 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , t->pantstexture );
2806 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , t->shirttexture );
2807 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , t->reflectmasktexture );
2808 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2809 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2810 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2811 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2812 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2813 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2814 if (rsurfacepass == RSURFPASS_BACKGROUND)
2816 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);
2817 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);
2818 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);
2822 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);
2824 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2825 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2826 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2827 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2829 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2830 if (rsurface.rtlight)
2832 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2833 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2836 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2839 case RENDERPATH_GL11:
2840 case RENDERPATH_GL13:
2841 case RENDERPATH_GLES1:
2843 case RENDERPATH_SOFT:
2844 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);
2845 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2846 R_SetupShader_SetPermutationSoft(mode, permutation);
2847 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2848 if (mode == SHADERMODE_LIGHTSOURCE)
2850 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2852 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2854 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2857 // additive passes are only darkened by fog, not tinted
2858 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2859 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2863 if (mode == SHADERMODE_FLATCOLOR)
2865 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2867 else if (mode == SHADERMODE_LIGHTDIRECTION)
2869 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2870 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2871 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2872 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2877 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2878 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2879 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2882 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2883 // additive passes are only darkened by fog, not tinted
2884 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2885 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2888 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2889 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]);
2890 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]);
2891 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2892 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2893 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2894 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2895 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2896 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2898 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2899 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2900 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2901 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2903 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]);
2904 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]);
2908 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]);
2909 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]);
2912 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2913 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2914 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2917 if (t->pantstexture)
2918 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2922 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2924 if (t->shirttexture)
2925 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2927 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2929 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934 r_glsl_offsetmapping_scale.value*t->offsetscale,
2935 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2939 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2941 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2944 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2945 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2946 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2947 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2948 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2949 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2950 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2951 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2952 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2953 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2954 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2955 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2956 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2957 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2958 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2961 if (rsurfacepass == RSURFPASS_BACKGROUND)
2963 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2969 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2972 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2973 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2974 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2976 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977 if (rsurface.rtlight)
2979 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2980 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2989 // select a permutation of the lighting shader appropriate to this
2990 // combination of texture, entity, light source, and fogging, only use the
2991 // minimum features necessary to avoid wasting rendering time in the
2992 // fragment shader on features that are not being used
2993 dpuint64 permutation = 0;
2994 unsigned int mode = 0;
2995 const float *lightcolorbase = rtlight->currentcolor;
2996 float ambientscale = rtlight->ambientscale;
2997 float diffusescale = rtlight->diffusescale;
2998 float specularscale = rtlight->specularscale;
2999 // this is the location of the light in view space
3000 vec3_t viewlightorigin;
3001 // this transforms from view space (camera) to light space (cubemap)
3002 matrix4x4_t viewtolight;
3003 matrix4x4_t lighttoview;
3004 float viewtolight16f[16];
3006 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007 if (rtlight->currentcubemap != r_texture_whitecube)
3008 permutation |= SHADERPERMUTATION_CUBEFILTER;
3009 if (diffusescale > 0)
3010 permutation |= SHADERPERMUTATION_DIFFUSE;
3011 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013 if (r_shadow_usingshadowmap2d)
3015 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016 if (r_shadow_shadowmapvsdct)
3017 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3019 if (r_shadow_shadowmap2ddepthbuffer)
3020 permutation |= SHADERPERMUTATION_DEPTHRGB;
3022 if (vid.allowalphatocoverage)
3023 GL_AlphaToCoverage(false);
3024 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3027 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028 switch(vid.renderpath)
3030 case RENDERPATH_D3D9:
3032 R_SetupShader_SetPermutationHLSL(mode, permutation);
3033 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3039 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3040 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);
3041 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3044 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3045 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3046 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3047 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3048 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3051 case RENDERPATH_D3D10:
3052 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054 case RENDERPATH_D3D11:
3055 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057 case RENDERPATH_GL20:
3058 case RENDERPATH_GLES2:
3059 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3062 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065 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]);
3066 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]);
3067 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);
3068 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]);
3069 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3071 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3072 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3073 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3074 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3075 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3077 case RENDERPATH_GL11:
3078 case RENDERPATH_GL13:
3079 case RENDERPATH_GLES1:
3081 case RENDERPATH_SOFT:
3082 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3085 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088 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]);
3089 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]);
3090 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);
3091 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3094 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3095 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3096 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3097 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3098 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3103 #define SKINFRAME_HASH 1024
3107 unsigned int loadsequence; // incremented each level change
3108 memexpandablearray_t array;
3109 skinframe_t *hash[SKINFRAME_HASH];
3112 r_skinframe_t r_skinframe;
3114 void R_SkinFrame_PrepareForPurge(void)
3116 r_skinframe.loadsequence++;
3117 // wrap it without hitting zero
3118 if (r_skinframe.loadsequence >= 200)
3119 r_skinframe.loadsequence = 1;
3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3126 // mark the skinframe as used for the purging code
3127 skinframe->loadsequence = r_skinframe.loadsequence;
3130 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3132 if (s->merged == s->base)
3134 R_PurgeTexture(s->stain); s->stain = NULL;
3135 R_PurgeTexture(s->merged); s->merged = NULL;
3136 R_PurgeTexture(s->base); s->base = NULL;
3137 R_PurgeTexture(s->pants); s->pants = NULL;
3138 R_PurgeTexture(s->shirt); s->shirt = NULL;
3139 R_PurgeTexture(s->nmap); s->nmap = NULL;
3140 R_PurgeTexture(s->gloss); s->gloss = NULL;
3141 R_PurgeTexture(s->glow); s->glow = NULL;
3142 R_PurgeTexture(s->fog); s->fog = NULL;
3143 R_PurgeTexture(s->reflect); s->reflect = NULL;
3144 s->loadsequence = 0;
3147 void R_SkinFrame_Purge(void)
3151 for (i = 0;i < SKINFRAME_HASH;i++)
3153 for (s = r_skinframe.hash[i];s;s = s->next)
3155 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3156 R_SkinFrame_PurgeSkinFrame(s);
3161 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3163 char basename[MAX_QPATH];
3165 Image_StripImageExtension(name, basename, sizeof(basename));
3167 if( last == NULL ) {
3169 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170 item = r_skinframe.hash[hashindex];
3175 // linearly search through the hash bucket
3176 for( ; item ; item = item->next ) {
3177 if( !strcmp( item->basename, basename ) ) {
3184 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3188 char basename[MAX_QPATH];
3190 Image_StripImageExtension(name, basename, sizeof(basename));
3192 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3193 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3194 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3201 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202 memset(item, 0, sizeof(*item));
3203 strlcpy(item->basename, basename, sizeof(item->basename));
3204 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205 item->comparewidth = comparewidth;
3206 item->compareheight = compareheight;
3207 item->comparecrc = comparecrc;
3208 item->next = r_skinframe.hash[hashindex];
3209 r_skinframe.hash[hashindex] = item;
3211 else if (textureflags & TEXF_FORCE_RELOAD)
3215 R_SkinFrame_PurgeSkinFrame(item);
3218 R_SkinFrame_MarkUsed(item);
3222 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3224 unsigned long long avgcolor[5], wsum; \
3232 for(pix = 0; pix < cnt; ++pix) \
3235 for(comp = 0; comp < 3; ++comp) \
3237 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3240 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3242 for(comp = 0; comp < 3; ++comp) \
3243 avgcolor[comp] += getpixel * w; \
3246 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3247 avgcolor[4] += getpixel; \
3249 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3251 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3252 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3253 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3254 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3257 extern cvar_t gl_picmip;
3258 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3261 unsigned char *pixels;
3262 unsigned char *bumppixels;
3263 unsigned char *basepixels = NULL;
3264 int basepixels_width = 0;
3265 int basepixels_height = 0;
3266 skinframe_t *skinframe;
3267 rtexture_t *ddsbase = NULL;
3268 qboolean ddshasalpha = false;
3269 float ddsavgcolor[4];
3270 char basename[MAX_QPATH];
3271 int miplevel = R_PicmipForFlags(textureflags);
3272 int savemiplevel = miplevel;
3276 if (cls.state == ca_dedicated)
3279 // return an existing skinframe if already loaded
3280 // if loading of the first image fails, don't make a new skinframe as it
3281 // would cause all future lookups of this to be missing
3282 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3283 if (skinframe && skinframe->base)
3286 Image_StripImageExtension(name, basename, sizeof(basename));
3288 // check for DDS texture file first
3289 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3291 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3292 if (basepixels == NULL && fallbacknotexture)
3293 basepixels = Image_GenerateNoTexture();
3294 if (basepixels == NULL)
3298 // FIXME handle miplevel
3300 if (developer_loading.integer)
3301 Con_Printf("loading skin \"%s\"\n", name);
3303 // we've got some pixels to store, so really allocate this new texture now
3305 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3306 textureflags &= ~TEXF_FORCE_RELOAD;
3307 skinframe->stain = NULL;
3308 skinframe->merged = NULL;
3309 skinframe->base = NULL;
3310 skinframe->pants = NULL;
3311 skinframe->shirt = NULL;
3312 skinframe->nmap = NULL;
3313 skinframe->gloss = NULL;
3314 skinframe->glow = NULL;
3315 skinframe->fog = NULL;
3316 skinframe->reflect = NULL;
3317 skinframe->hasalpha = false;
3318 // we could store the q2animname here too
3322 skinframe->base = ddsbase;
3323 skinframe->hasalpha = ddshasalpha;
3324 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3325 if (r_loadfog && skinframe->hasalpha)
3326 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);
3327 //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]);
3331 basepixels_width = image_width;
3332 basepixels_height = image_height;
3333 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);
3334 if (textureflags & TEXF_ALPHA)
3336 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3338 if (basepixels[j] < 255)
3340 skinframe->hasalpha = true;
3344 if (r_loadfog && skinframe->hasalpha)
3346 // has transparent pixels
3347 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3348 for (j = 0;j < image_width * image_height * 4;j += 4)
3353 pixels[j+3] = basepixels[j+3];
3355 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);
3359 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3361 //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]);
3362 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3363 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3364 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3365 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3371 mymiplevel = savemiplevel;
3372 if (r_loadnormalmap)
3373 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);
3374 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3376 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3377 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3378 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3379 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3382 // _norm is the name used by tenebrae and has been adopted as standard
3383 if (r_loadnormalmap && skinframe->nmap == NULL)
3385 mymiplevel = savemiplevel;
3386 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3388 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);
3392 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3394 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3395 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3396 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);
3398 Mem_Free(bumppixels);
3400 else if (r_shadow_bumpscale_basetexture.value > 0)
3402 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3403 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3404 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);
3408 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3409 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3413 // _luma is supported only for tenebrae compatibility
3414 // _glow is the preferred name
3415 mymiplevel = savemiplevel;
3416 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))))
3418 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);
3420 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3421 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3423 Mem_Free(pixels);pixels = NULL;
3426 mymiplevel = savemiplevel;
3427 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3429 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);
3431 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3432 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3438 mymiplevel = savemiplevel;
3439 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3441 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);
3443 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3444 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3450 mymiplevel = savemiplevel;
3451 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3453 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);
3455 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3456 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3462 mymiplevel = savemiplevel;
3463 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3465 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);
3467 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3468 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3475 Mem_Free(basepixels);
3480 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3481 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3484 skinframe_t *skinframe;
3487 if (cls.state == ca_dedicated)
3490 // if already loaded just return it, otherwise make a new skinframe
3491 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3492 if (skinframe->base)
3494 textureflags &= ~TEXF_FORCE_RELOAD;
3496 skinframe->stain = NULL;
3497 skinframe->merged = NULL;
3498 skinframe->base = NULL;
3499 skinframe->pants = NULL;
3500 skinframe->shirt = NULL;
3501 skinframe->nmap = NULL;
3502 skinframe->gloss = NULL;
3503 skinframe->glow = NULL;
3504 skinframe->fog = NULL;
3505 skinframe->reflect = NULL;
3506 skinframe->hasalpha = false;
3508 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3512 if (developer_loading.integer)
3513 Con_Printf("loading 32bit skin \"%s\"\n", name);
3515 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3517 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3518 unsigned char *b = a + width * height * 4;
3519 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3520 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);
3523 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3524 if (textureflags & TEXF_ALPHA)
3526 for (i = 3;i < width * height * 4;i += 4)
3528 if (skindata[i] < 255)
3530 skinframe->hasalpha = true;
3534 if (r_loadfog && skinframe->hasalpha)
3536 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3537 memcpy(fogpixels, skindata, width * height * 4);
3538 for (i = 0;i < width * height * 4;i += 4)
3539 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3540 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3541 Mem_Free(fogpixels);
3545 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3546 //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]);
3551 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3555 skinframe_t *skinframe;
3557 if (cls.state == ca_dedicated)
3560 // if already loaded just return it, otherwise make a new skinframe
3561 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3562 if (skinframe->base)
3564 //textureflags &= ~TEXF_FORCE_RELOAD;
3566 skinframe->stain = NULL;
3567 skinframe->merged = NULL;
3568 skinframe->base = NULL;
3569 skinframe->pants = NULL;
3570 skinframe->shirt = NULL;
3571 skinframe->nmap = NULL;
3572 skinframe->gloss = NULL;
3573 skinframe->glow = NULL;
3574 skinframe->fog = NULL;
3575 skinframe->reflect = NULL;
3576 skinframe->hasalpha = false;
3578 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582 if (developer_loading.integer)
3583 Con_Printf("loading quake skin \"%s\"\n", name);
3585 // 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)
3586 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3587 memcpy(skinframe->qpixels, skindata, width*height);
3588 skinframe->qwidth = width;
3589 skinframe->qheight = height;
3592 for (i = 0;i < width * height;i++)
3593 featuresmask |= palette_featureflags[skindata[i]];
3595 skinframe->hasalpha = false;
3598 skinframe->hasalpha = true;
3599 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3600 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3601 skinframe->qgeneratemerged = true;
3602 skinframe->qgeneratebase = skinframe->qhascolormapping;
3603 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3605 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3606 //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]);
3611 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3615 unsigned char *skindata;
3618 if (!skinframe->qpixels)
3621 if (!skinframe->qhascolormapping)
3622 colormapped = false;
3626 if (!skinframe->qgeneratebase)
3631 if (!skinframe->qgeneratemerged)
3635 width = skinframe->qwidth;
3636 height = skinframe->qheight;
3637 skindata = skinframe->qpixels;
3639 if (skinframe->qgeneratenmap)
3641 unsigned char *a, *b;
3642 skinframe->qgeneratenmap = false;
3643 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3644 b = a + width * height * 4;
3645 // use either a custom palette or the quake palette
3646 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3647 Image_HeightmapToNormalmap_BGRA(a, 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, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3652 if (skinframe->qgenerateglow)
3654 skinframe->qgenerateglow = false;
3655 if (skinframe->hasalpha) // fence textures
3656 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
3658 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
3663 skinframe->qgeneratebase = false;
3664 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);
3665 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);
3666 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);
3670 skinframe->qgeneratemerged = false;
3671 if (skinframe->hasalpha) // fence textures
3672 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);
3674 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);
3677 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3679 Mem_Free(skinframe->qpixels);
3680 skinframe->qpixels = NULL;
3684 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)
3687 skinframe_t *skinframe;
3690 if (cls.state == ca_dedicated)
3693 // if already loaded just return it, otherwise make a new skinframe
3694 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3695 if (skinframe->base)
3697 textureflags &= ~TEXF_FORCE_RELOAD;
3699 skinframe->stain = NULL;
3700 skinframe->merged = NULL;
3701 skinframe->base = NULL;
3702 skinframe->pants = NULL;
3703 skinframe->shirt = NULL;
3704 skinframe->nmap = NULL;
3705 skinframe->gloss = NULL;
3706 skinframe->glow = NULL;
3707 skinframe->fog = NULL;
3708 skinframe->reflect = NULL;
3709 skinframe->hasalpha = false;
3711 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3715 if (developer_loading.integer)
3716 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3718 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3719 if ((textureflags & TEXF_ALPHA) && alphapalette)
3721 for (i = 0;i < width * height;i++)
3723 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3725 skinframe->hasalpha = true;
3729 if (r_loadfog && skinframe->hasalpha)
3730 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3733 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[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 skinframe_t *R_SkinFrame_LoadMissing(void)
3741 skinframe_t *skinframe;
3743 if (cls.state == ca_dedicated)
3746 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3747 skinframe->stain = NULL;
3748 skinframe->merged = NULL;
3749 skinframe->base = NULL;
3750 skinframe->pants = NULL;
3751 skinframe->shirt = NULL;
3752 skinframe->nmap = NULL;
3753 skinframe->gloss = NULL;
3754 skinframe->glow = NULL;
3755 skinframe->fog = NULL;
3756 skinframe->reflect = NULL;
3757 skinframe->hasalpha = false;
3759 skinframe->avgcolor[0] = rand() / RAND_MAX;
3760 skinframe->avgcolor[1] = rand() / RAND_MAX;
3761 skinframe->avgcolor[2] = rand() / RAND_MAX;
3762 skinframe->avgcolor[3] = 1;
3767 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3770 static unsigned char pix[16][16][4];
3772 if (cls.state == ca_dedicated)
3775 // this makes a light grey/dark grey checkerboard texture
3778 for (y = 0; y < 16; y++)
3780 for (x = 0; x < 16; x++)
3782 if ((y < 8) ^ (x < 8))
3800 return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3803 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3805 skinframe_t *skinframe;
3806 if (cls.state == ca_dedicated)
3808 // if already loaded just return it, otherwise make a new skinframe
3809 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3810 if (skinframe->base)
3812 textureflags &= ~TEXF_FORCE_RELOAD;
3813 skinframe->stain = NULL;
3814 skinframe->merged = NULL;
3815 skinframe->base = NULL;
3816 skinframe->pants = NULL;
3817 skinframe->shirt = NULL;
3818 skinframe->nmap = NULL;
3819 skinframe->gloss = NULL;
3820 skinframe->glow = NULL;
3821 skinframe->fog = NULL;
3822 skinframe->reflect = NULL;
3823 skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3824 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3827 if (developer_loading.integer)
3828 Con_Printf("loading 32bit skin \"%s\"\n", name);
3829 skinframe->base = skinframe->merged = tex;
3830 Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3834 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3835 typedef struct suffixinfo_s
3838 qboolean flipx, flipy, flipdiagonal;
3841 static suffixinfo_t suffix[3][6] =
3844 {"px", false, false, false},
3845 {"nx", false, false, false},
3846 {"py", false, false, false},
3847 {"ny", false, false, false},
3848 {"pz", false, false, false},
3849 {"nz", false, false, false}
3852 {"posx", false, false, false},
3853 {"negx", false, false, false},
3854 {"posy", false, false, false},
3855 {"negy", false, false, false},
3856 {"posz", false, false, false},
3857 {"negz", false, false, false}
3860 {"rt", true, false, true},
3861 {"lf", false, true, true},
3862 {"ft", true, true, false},
3863 {"bk", false, false, false},
3864 {"up", true, false, true},
3865 {"dn", true, false, true}
3869 static int componentorder[4] = {0, 1, 2, 3};
3871 static rtexture_t *R_LoadCubemap(const char *basename)
3873 int i, j, cubemapsize;
3874 unsigned char *cubemappixels, *image_buffer;
3875 rtexture_t *cubemaptexture;
3877 // must start 0 so the first loadimagepixels has no requested width/height
3879 cubemappixels = NULL;
3880 cubemaptexture = NULL;
3881 // keep trying different suffix groups (posx, px, rt) until one loads
3882 for (j = 0;j < 3 && !cubemappixels;j++)
3884 // load the 6 images in the suffix group
3885 for (i = 0;i < 6;i++)
3887 // generate an image name based on the base and and suffix
3888 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3890 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3892 // an image loaded, make sure width and height are equal
3893 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3895 // if this is the first image to load successfully, allocate the cubemap memory
3896 if (!cubemappixels && image_width >= 1)
3898 cubemapsize = image_width;
3899 // note this clears to black, so unavailable sides are black
3900 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3902 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3904 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);
3907 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3909 Mem_Free(image_buffer);
3913 // if a cubemap loaded, upload it
3916 if (developer_loading.integer)
3917 Con_Printf("loading cubemap \"%s\"\n", basename);
3919 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);
3920 Mem_Free(cubemappixels);
3924 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3925 if (developer_loading.integer)
3927 Con_Printf("(tried tried images ");
3928 for (j = 0;j < 3;j++)
3929 for (i = 0;i < 6;i++)
3930 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3931 Con_Print(" and was unable to find any of them).\n");
3934 return cubemaptexture;
3937 rtexture_t *R_GetCubemap(const char *basename)
3940 for (i = 0;i < r_texture_numcubemaps;i++)
3941 if (r_texture_cubemaps[i] != NULL)
3942 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3943 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3944 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3945 return r_texture_whitecube;
3946 r_texture_numcubemaps++;
3947 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3948 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3949 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3950 return r_texture_cubemaps[i]->texture;
3953 static void R_Main_FreeViewCache(void)
3955 if (r_refdef.viewcache.entityvisible)
3956 Mem_Free(r_refdef.viewcache.entityvisible);
3957 if (r_refdef.viewcache.world_pvsbits)
3958 Mem_Free(r_refdef.viewcache.world_pvsbits);
3959 if (r_refdef.viewcache.world_leafvisible)
3960 Mem_Free(r_refdef.viewcache.world_leafvisible);
3961 if (r_refdef.viewcache.world_surfacevisible)
3962 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3963 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3966 static void R_Main_ResizeViewCache(void)
3968 int numentities = r_refdef.scene.numentities;
3969 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3970 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3971 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3972 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3973 if (r_refdef.viewcache.maxentities < numentities)
3975 r_refdef.viewcache.maxentities = numentities;
3976 if (r_refdef.viewcache.entityvisible)
3977 Mem_Free(r_refdef.viewcache.entityvisible);
3978 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3980 if (r_refdef.viewcache.world_numclusters != numclusters)
3982 r_refdef.viewcache.world_numclusters = numclusters;
3983 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3984 if (r_refdef.viewcache.world_pvsbits)
3985 Mem_Free(r_refdef.viewcache.world_pvsbits);
3986 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3988 if (r_refdef.viewcache.world_numleafs != numleafs)
3990 r_refdef.viewcache.world_numleafs = numleafs;
3991 if (r_refdef.viewcache.world_leafvisible)
3992 Mem_Free(r_refdef.viewcache.world_leafvisible);
3993 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3995 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3997 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3998 if (r_refdef.viewcache.world_surfacevisible)
3999 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4000 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4004 extern rtexture_t *loadingscreentexture;
4005 static void gl_main_start(void)
4007 loadingscreentexture = NULL;
4008 r_texture_blanknormalmap = NULL;
4009 r_texture_white = NULL;
4010 r_texture_grey128 = NULL;
4011 r_texture_black = NULL;
4012 r_texture_whitecube = NULL;
4013 r_texture_normalizationcube = NULL;
4014 r_texture_fogattenuation = NULL;
4015 r_texture_fogheighttexture = NULL;
4016 r_texture_gammaramps = NULL;
4017 r_texture_numcubemaps = 0;
4018 r_uniformbufferalignment = 32;
4020 r_loaddds = r_texture_dds_load.integer != 0;
4021 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4023 switch(vid.renderpath)
4025 case RENDERPATH_GL20:
4026 case RENDERPATH_D3D9:
4027 case RENDERPATH_D3D10:
4028 case RENDERPATH_D3D11:
4029 case RENDERPATH_SOFT:
4030 case RENDERPATH_GLES2:
4031 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4032 Cvar_SetValueQuick(&gl_combine, 1);
4033 Cvar_SetValueQuick(&r_glsl, 1);
4034 r_loadnormalmap = true;
4037 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4038 if (vid.support.arb_uniform_buffer_object)
4039 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4042 case RENDERPATH_GL13:
4043 case RENDERPATH_GLES1:
4044 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4045 Cvar_SetValueQuick(&gl_combine, 1);
4046 Cvar_SetValueQuick(&r_glsl, 0);
4047 r_loadnormalmap = false;
4048 r_loadgloss = false;
4051 case RENDERPATH_GL11:
4052 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4053 Cvar_SetValueQuick(&gl_combine, 0);
4054 Cvar_SetValueQuick(&r_glsl, 0);
4055 r_loadnormalmap = false;
4056 r_loadgloss = false;
4062 R_FrameData_Reset();
4063 R_BufferData_Reset();
4067 memset(r_queries, 0, sizeof(r_queries));
4069 r_qwskincache = NULL;
4070 r_qwskincache_size = 0;
4072 // due to caching of texture_t references, the collision cache must be reset
4073 Collision_Cache_Reset(true);
4075 // set up r_skinframe loading system for textures
4076 memset(&r_skinframe, 0, sizeof(r_skinframe));
4077 r_skinframe.loadsequence = 1;
4078 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4080 r_main_texturepool = R_AllocTexturePool();
4081 R_BuildBlankTextures();
4083 if (vid.support.arb_texture_cube_map)
4086 R_BuildNormalizationCube();
4088 r_texture_fogattenuation = NULL;
4089 r_texture_fogheighttexture = NULL;
4090 r_texture_gammaramps = NULL;
4091 //r_texture_fogintensity = NULL;
4092 memset(&r_fb, 0, sizeof(r_fb));
4093 r_glsl_permutation = NULL;
4094 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4095 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4097 r_hlsl_permutation = NULL;
4098 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4099 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4101 memset(&r_svbsp, 0, sizeof (r_svbsp));
4103 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4104 r_texture_numcubemaps = 0;
4106 r_refdef.fogmasktable_density = 0;
4109 // For Steelstorm Android
4110 // FIXME CACHE the program and reload
4111 // FIXME see possible combinations for SS:BR android
4112 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4113 R_SetupShader_SetPermutationGLSL(0, 12);
4114 R_SetupShader_SetPermutationGLSL(0, 13);
4115 R_SetupShader_SetPermutationGLSL(0, 8388621);
4116 R_SetupShader_SetPermutationGLSL(3, 0);
4117 R_SetupShader_SetPermutationGLSL(3, 2048);
4118 R_SetupShader_SetPermutationGLSL(5, 0);
4119 R_SetupShader_SetPermutationGLSL(5, 2);
4120 R_SetupShader_SetPermutationGLSL(5, 2048);
4121 R_SetupShader_SetPermutationGLSL(5, 8388608);
4122 R_SetupShader_SetPermutationGLSL(11, 1);
4123 R_SetupShader_SetPermutationGLSL(11, 2049);
4124 R_SetupShader_SetPermutationGLSL(11, 8193);
4125 R_SetupShader_SetPermutationGLSL(11, 10241);
4126 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4130 static void gl_main_shutdown(void)
4133 R_FrameData_Reset();
4134 R_BufferData_Reset();
4136 R_Main_FreeViewCache();
4138 switch(vid.renderpath)
4140 case RENDERPATH_GL11:
4141 case RENDERPATH_GL13:
4142 case RENDERPATH_GL20:
4143 case RENDERPATH_GLES1:
4144 case RENDERPATH_GLES2:
4145 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4147 qglDeleteQueriesARB(r_maxqueries, r_queries);
4150 case RENDERPATH_D3D9:
4151 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4153 case RENDERPATH_D3D10:
4154 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4156 case RENDERPATH_D3D11:
4157 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4159 case RENDERPATH_SOFT:
4165 memset(r_queries, 0, sizeof(r_queries));
4167 r_qwskincache = NULL;
4168 r_qwskincache_size = 0;
4170 // clear out the r_skinframe state
4171 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4172 memset(&r_skinframe, 0, sizeof(r_skinframe));
4175 Mem_Free(r_svbsp.nodes);
4176 memset(&r_svbsp, 0, sizeof (r_svbsp));
4177 R_FreeTexturePool(&r_main_texturepool);
4178 loadingscreentexture = NULL;
4179 r_texture_blanknormalmap = NULL;
4180 r_texture_white = NULL;
4181 r_texture_grey128 = NULL;
4182 r_texture_black = NULL;
4183 r_texture_whitecube = NULL;
4184 r_texture_normalizationcube = NULL;
4185 r_texture_fogattenuation = NULL;
4186 r_texture_fogheighttexture = NULL;
4187 r_texture_gammaramps = NULL;
4188 r_texture_numcubemaps = 0;
4189 //r_texture_fogintensity = NULL;
4190 memset(&r_fb, 0, sizeof(r_fb));
4193 r_glsl_permutation = NULL;
4194 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4195 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4197 r_hlsl_permutation = NULL;
4198 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4199 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4203 static void gl_main_newmap(void)
4205 // FIXME: move this code to client
4206 char *entities, entname[MAX_QPATH];
4208 Mem_Free(r_qwskincache);
4209 r_qwskincache = NULL;
4210 r_qwskincache_size = 0;
4213 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4214 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4216 CL_ParseEntityLump(entities);
4220 if (cl.worldmodel->brush.entities)
4221 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4223 R_Main_FreeViewCache();
4225 R_FrameData_Reset();
4226 R_BufferData_Reset();
4229 void GL_Main_Init(void)
4232 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4233 R_InitShaderModeInfo();
4235 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4236 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4237 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4238 if (gamemode == GAME_NEHAHRA)
4240 Cvar_RegisterVariable (&gl_fogenable);
4241 Cvar_RegisterVariable (&gl_fogdensity);
4242 Cvar_RegisterVariable (&gl_fogred);
4243 Cvar_RegisterVariable (&gl_foggreen);
4244 Cvar_RegisterVariable (&gl_fogblue);
4245 Cvar_RegisterVariable (&gl_fogstart);
4246 Cvar_RegisterVariable (&gl_fogend);
4247 Cvar_RegisterVariable (&gl_skyclip);
4249 Cvar_RegisterVariable(&r_motionblur);
4250 Cvar_RegisterVariable(&r_damageblur);
4251 Cvar_RegisterVariable(&r_motionblur_averaging);
4252 Cvar_RegisterVariable(&r_motionblur_randomize);
4253 Cvar_RegisterVariable(&r_motionblur_minblur);
4254 Cvar_RegisterVariable(&r_motionblur_maxblur);
4255 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4256 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4257 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4258 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4259 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4260 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4261 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4262 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4263 Cvar_RegisterVariable(&r_equalize_entities_by);
4264 Cvar_RegisterVariable(&r_equalize_entities_to);
4265 Cvar_RegisterVariable(&r_depthfirst);
4266 Cvar_RegisterVariable(&r_useinfinitefarclip);
4267 Cvar_RegisterVariable(&r_farclip_base);
4268 Cvar_RegisterVariable(&r_farclip_world);
4269 Cvar_RegisterVariable(&r_nearclip);
4270 Cvar_RegisterVariable(&r_deformvertexes);
4271 Cvar_RegisterVariable(&r_transparent);
4272 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4273 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4274 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4275 Cvar_RegisterVariable(&r_showoverdraw);
4276 Cvar_RegisterVariable(&r_showbboxes);
4277 Cvar_RegisterVariable(&r_showbboxes_client);
4278 Cvar_RegisterVariable(&r_showsurfaces);
4279 Cvar_RegisterVariable(&r_showtris);
4280 Cvar_RegisterVariable(&r_shownormals);
4281 Cvar_RegisterVariable(&r_showlighting);
4282 Cvar_RegisterVariable(&r_showshadowvolumes);
4283 Cvar_RegisterVariable(&r_showcollisionbrushes);
4284 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4285 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4286 Cvar_RegisterVariable(&r_showdisabledepthtest);
4287 Cvar_RegisterVariable(&r_drawportals);
4288 Cvar_RegisterVariable(&r_drawentities);
4289 Cvar_RegisterVariable(&r_draw2d);
4290 Cvar_RegisterVariable(&r_drawworld);
4291 Cvar_RegisterVariable(&r_cullentities_trace);
4292 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4293 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4294 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4295 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4296 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4297 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4298 Cvar_RegisterVariable(&r_sortentities);
4299 Cvar_RegisterVariable(&r_drawviewmodel);
4300 Cvar_RegisterVariable(&r_drawexteriormodel);
4301 Cvar_RegisterVariable(&r_speeds);
4302 Cvar_RegisterVariable(&r_fullbrights);
4303 Cvar_RegisterVariable(&r_wateralpha);
4304 Cvar_RegisterVariable(&r_dynamic);
4305 Cvar_RegisterVariable(&r_fakelight);
4306 Cvar_RegisterVariable(&r_fakelight_intensity);
4307 Cvar_RegisterVariable(&r_fullbright_directed);
4308 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4309 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4310 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4311 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4312 Cvar_RegisterVariable(&r_fullbright);
4313 Cvar_RegisterVariable(&r_shadows);
4314 Cvar_RegisterVariable(&r_shadows_darken);
4315 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4316 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4317 Cvar_RegisterVariable(&r_shadows_throwdistance);
4318 Cvar_RegisterVariable(&r_shadows_throwdirection);
4319 Cvar_RegisterVariable(&r_shadows_focus);
4320 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4321 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4322 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4323 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4324 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4325 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4326 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4327 Cvar_RegisterVariable(&r_fog_exp2);
4328 Cvar_RegisterVariable(&r_fog_clear);
4329 Cvar_RegisterVariable(&r_drawfog);
4330 Cvar_RegisterVariable(&r_transparentdepthmasking);
4331 Cvar_RegisterVariable(&r_transparent_sortmindist);
4332 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4333 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4334 Cvar_RegisterVariable(&r_texture_dds_load);
4335 Cvar_RegisterVariable(&r_texture_dds_save);
4336 Cvar_RegisterVariable(&r_textureunits);
4337 Cvar_RegisterVariable(&gl_combine);
4338 Cvar_RegisterVariable(&r_usedepthtextures);
4339 Cvar_RegisterVariable(&r_viewfbo);
4340 Cvar_RegisterVariable(&r_viewscale);
4341 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4342 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4343 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4344 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4345 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4346 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4347 Cvar_RegisterVariable(&r_glsl);
4348 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4349 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4350 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4351 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4352 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4353 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4354 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4355 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4356 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4357 Cvar_RegisterVariable(&r_glsl_postprocess);
4358 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4359 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4360 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4361 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4362 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4363 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4364 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4365 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4366 Cvar_RegisterVariable(&r_celshading);
4367 Cvar_RegisterVariable(&r_celoutlines);
4369 Cvar_RegisterVariable(&r_water);
4370 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4371 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4372 Cvar_RegisterVariable(&r_water_clippingplanebias);
4373 Cvar_RegisterVariable(&r_water_refractdistort);
4374 Cvar_RegisterVariable(&r_water_reflectdistort);
4375 Cvar_RegisterVariable(&r_water_scissormode);
4376 Cvar_RegisterVariable(&r_water_lowquality);
4377 Cvar_RegisterVariable(&r_water_hideplayer);
4378 Cvar_RegisterVariable(&r_water_fbo);
4380 Cvar_RegisterVariable(&r_lerpsprites);
4381 Cvar_RegisterVariable(&r_lerpmodels);
4382 Cvar_RegisterVariable(&r_lerplightstyles);
4383 Cvar_RegisterVariable(&r_waterscroll);
4384 Cvar_RegisterVariable(&r_bloom);
4385 Cvar_RegisterVariable(&r_bloom_colorscale);
4386 Cvar_RegisterVariable(&r_bloom_brighten);
4387 Cvar_RegisterVariable(&r_bloom_blur);
4388 Cvar_RegisterVariable(&r_bloom_resolution);
4389 Cvar_RegisterVariable(&r_bloom_colorexponent);
4390 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4391 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4392 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4393 Cvar_RegisterVariable(&r_hdr_glowintensity);
4394 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4395 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4396 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4397 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4398 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4399 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4400 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4401 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4402 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4403 Cvar_RegisterVariable(&developer_texturelogging);
4404 Cvar_RegisterVariable(&gl_lightmaps);
4405 Cvar_RegisterVariable(&r_test);
4406 Cvar_RegisterVariable(&r_batch_multidraw);
4407 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4408 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4409 Cvar_RegisterVariable(&r_glsl_skeletal);
4410 Cvar_RegisterVariable(&r_glsl_saturation);
4411 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4412 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4413 Cvar_RegisterVariable(&r_framedatasize);
4414 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4415 Cvar_RegisterVariable(&r_buffermegs[i]);
4416 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4417 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4418 Cvar_SetValue("r_fullbrights", 0);
4419 #ifdef DP_MOBILETOUCH
4420 // GLES devices have terrible depth precision in general, so...
4421 Cvar_SetValueQuick(&r_nearclip, 4);
4422 Cvar_SetValueQuick(&r_farclip_base, 4096);
4423 Cvar_SetValueQuick(&r_farclip_world, 0);
4424 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4426 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4429 void Render_Init(void)
4442 R_LightningBeams_Init();
4452 extern char *ENGINE_EXTENSIONS;
4455 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4456 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4457 gl_version = (const char *)qglGetString(GL_VERSION);
4458 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4462 if (!gl_platformextensions)
4463 gl_platformextensions = "";
4465 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4466 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4467 Con_Printf("GL_VERSION: %s\n", gl_version);
4468 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4469 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4471 VID_CheckExtensions();
4473 // LordHavoc: report supported extensions
4475 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4477 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4480 // clear to black (loading plaque will be seen over this)
4481 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4485 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4489 if (r_trippy.integer)
4491 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4493 p = r_refdef.view.frustum + i;
4498 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4502 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4506 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4510 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4514 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4518 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4522 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4526 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4534 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4538 if (r_trippy.integer)
4540 for (i = 0;i < numplanes;i++)
4547 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4551 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4555 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4559 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4563 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4567 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4571 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4575 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4583 //==================================================================================
4585 // LordHavoc: this stores temporary data used within the same frame
4587 typedef struct r_framedata_mem_s
4589 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4590 size_t size; // how much usable space
4591 size_t current; // how much space in use
4592 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4593 size_t wantedsize; // how much space was allocated
4594 unsigned char *data; // start of real data (16byte aligned)
4598 static r_framedata_mem_t *r_framedata_mem;
4600 void R_FrameData_Reset(void)
4602 while (r_framedata_mem)
4604 r_framedata_mem_t *next = r_framedata_mem->purge;
4605 Mem_Free(r_framedata_mem);
4606 r_framedata_mem = next;
4610 static void R_FrameData_Resize(qboolean mustgrow)
4613 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4614 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4615 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4617 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4618 newmem->wantedsize = wantedsize;
4619 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4620 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4621 newmem->current = 0;
4623 newmem->purge = r_framedata_mem;
4624 r_framedata_mem = newmem;
4628 void R_FrameData_NewFrame(void)
4630 R_FrameData_Resize(false);
4631 if (!r_framedata_mem)
4633 // if we ran out of space on the last frame, free the old memory now
4634 while (r_framedata_mem->purge)
4636 // repeatedly remove the second item in the list, leaving only head
4637 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4638 Mem_Free(r_framedata_mem->purge);
4639 r_framedata_mem->purge = next;
4641 // reset the current mem pointer
4642 r_framedata_mem->current = 0;
4643 r_framedata_mem->mark = 0;
4646 void *R_FrameData_Alloc(size_t size)
4651 // align to 16 byte boundary - the data pointer is already aligned, so we
4652 // only need to ensure the size of every allocation is also aligned
4653 size = (size + 15) & ~15;
4655 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4657 // emergency - we ran out of space, allocate more memory
4658 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4659 newvalue = r_framedatasize.value * 2.0f;
4660 // 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
4661 if (sizeof(size_t) >= 8)
4662 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4664 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4665 // this might not be a growing it, but we'll allocate another buffer every time
4666 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4667 R_FrameData_Resize(true);
4670 data = r_framedata_mem->data + r_framedata_mem->current;
4671 r_framedata_mem->current += size;
4673 // count the usage for stats
4674 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4675 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4677 return (void *)data;
4680 void *R_FrameData_Store(size_t size, void *data)
4682 void *d = R_FrameData_Alloc(size);
4684 memcpy(d, data, size);
4688 void R_FrameData_SetMark(void)
4690 if (!r_framedata_mem)
4692 r_framedata_mem->mark = r_framedata_mem->current;
4695 void R_FrameData_ReturnToMark(void)
4697 if (!r_framedata_mem)
4699 r_framedata_mem->current = r_framedata_mem->mark;
4702 //==================================================================================
4704 // avoid reusing the same buffer objects on consecutive frames
4705 #define R_BUFFERDATA_CYCLE 3
4707 typedef struct r_bufferdata_buffer_s
4709 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4710 size_t size; // how much usable space
4711 size_t current; // how much space in use
4712 r_meshbuffer_t *buffer; // the buffer itself
4714 r_bufferdata_buffer_t;
4716 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4717 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4719 /// frees all dynamic buffers
4720 void R_BufferData_Reset(void)
4723 r_bufferdata_buffer_t **p, *mem;
4724 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4726 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4729 p = &r_bufferdata_buffer[cycle][type];
4735 R_Mesh_DestroyMeshBuffer(mem->buffer);
4742 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4743 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4745 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4747 float newvalue = r_buffermegs[type].value;
4749 // increase the cvar if we have to (but only if we already have a mem)
4750 if (mustgrow && mem)
4752 newvalue = bound(0.25f, newvalue, 256.0f);
4753 while (newvalue * 1024*1024 < minsize)
4756 // clamp the cvar to valid range
4757 newvalue = bound(0.25f, newvalue, 256.0f);
4758 if (r_buffermegs[type].value != newvalue)
4759 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4761 // calculate size in bytes
4762 size = (size_t)(newvalue * 1024*1024);
4763 size = bound(131072, size, 256*1024*1024);
4765 // allocate a new buffer if the size is different (purge old one later)
4766 // or if we were told we must grow the buffer
4767 if (!mem || mem->size != size || mustgrow)
4769 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4772 if (type == R_BUFFERDATA_VERTEX)
4773 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4774 else if (type == R_BUFFERDATA_INDEX16)
4775 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4776 else if (type == R_BUFFERDATA_INDEX32)
4777 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4778 else if (type == R_BUFFERDATA_UNIFORM)
4779 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4780 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4781 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4785 void R_BufferData_NewFrame(void)
4788 r_bufferdata_buffer_t **p, *mem;
4789 // cycle to the next frame's buffers
4790 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4791 // if we ran out of space on the last time we used these buffers, free the old memory now
4792 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4794 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4796 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4797 // free all but the head buffer, this is how we recycle obsolete
4798 // buffers after they are no longer in use
4799 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4805 R_Mesh_DestroyMeshBuffer(mem->buffer);
4808 // reset the current offset
4809 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4814 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4816 r_bufferdata_buffer_t *mem;
4820 *returnbufferoffset = 0;
4822 // align size to a byte boundary appropriate for the buffer type, this
4823 // makes all allocations have aligned start offsets
4824 if (type == R_BUFFERDATA_UNIFORM)
4825 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4827 padsize = (datasize + 15) & ~15;
4829 // if we ran out of space in this buffer we must allocate a new one
4830 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)
4831 R_BufferData_Resize(type, true, padsize);
4833 // if the resize did not give us enough memory, fail
4834 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)
4835 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4837 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4838 offset = (int)mem->current;
4839 mem->current += padsize;
4841 // upload the data to the buffer at the chosen offset
4843 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4844 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4846 // count the usage for stats
4847 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4848 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4850 // return the buffer offset
4851 *returnbufferoffset = offset;
4856 //==================================================================================
4858 // LordHavoc: animcache originally written by Echon, rewritten since then
4861 * Animation cache prevents re-generating mesh data for an animated model
4862 * multiple times in one frame for lighting, shadowing, reflections, etc.
4865 void R_AnimCache_Free(void)
4869 void R_AnimCache_ClearCache(void)
4872 entity_render_t *ent;
4874 for (i = 0;i < r_refdef.scene.numentities;i++)
4876 ent = r_refdef.scene.entities[i];
4877 ent->animcache_vertex3f = NULL;
4878 ent->animcache_vertex3f_vertexbuffer = NULL;
4879 ent->animcache_vertex3f_bufferoffset = 0;
4880 ent->animcache_normal3f = NULL;
4881 ent->animcache_normal3f_vertexbuffer = NULL;
4882 ent->animcache_normal3f_bufferoffset = 0;
4883 ent->animcache_svector3f = NULL;
4884 ent->animcache_svector3f_vertexbuffer = NULL;
4885 ent->animcache_svector3f_bufferoffset = 0;
4886 ent->animcache_tvector3f = NULL;
4887 ent->animcache_tvector3f_vertexbuffer = NULL;
4888 ent->animcache_tvector3f_bufferoffset = 0;
4889 ent->animcache_vertexmesh = NULL;
4890 ent->animcache_vertexmesh_vertexbuffer = NULL;
4891 ent->animcache_vertexmesh_bufferoffset = 0;
4892 ent->animcache_skeletaltransform3x4 = NULL;
4893 ent->animcache_skeletaltransform3x4buffer = NULL;
4894 ent->animcache_skeletaltransform3x4offset = 0;
4895 ent->animcache_skeletaltransform3x4size = 0;
4899 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4903 // check if we need the meshbuffers
4904 if (!vid.useinterleavedarrays)
4907 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4908 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4909 // TODO: upload vertexbuffer?
4910 if (ent->animcache_vertexmesh)
4912 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4913 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4914 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4915 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4916 for (i = 0;i < numvertices;i++)
4917 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4918 if (ent->animcache_svector3f)
4919 for (i = 0;i < numvertices;i++)
4920 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4921 if (ent->animcache_tvector3f)
4922 for (i = 0;i < numvertices;i++)
4923 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4924 if (ent->animcache_normal3f)
4925 for (i = 0;i < numvertices;i++)
4926 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4930 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4932 dp_model_t *model = ent->model;
4935 // see if this ent is worth caching
4936 if (!model || !model->Draw || !model->AnimateVertices)
4938 // nothing to cache if it contains no animations and has no skeleton
4939 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4941 // see if it is already cached for gpuskeletal
4942 if (ent->animcache_skeletaltransform3x4)
4944 // see if it is already cached as a mesh
4945 if (ent->animcache_vertex3f)
4947 // check if we need to add normals or tangents
4948 if (ent->animcache_normal3f)
4949 wantnormals = false;
4950 if (ent->animcache_svector3f)
4951 wanttangents = false;
4952 if (!wantnormals && !wanttangents)
4956 // check which kind of cache we need to generate
4957 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4959 // cache the skeleton so the vertex shader can use it
4960 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4961 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4962 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4963 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4964 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4965 // note: this can fail if the buffer is at the grow limit
4966 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4967 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4969 else if (ent->animcache_vertex3f)
4971 // mesh was already cached but we may need to add normals/tangents
4972 // (this only happens with multiple views, reflections, cameras, etc)
4973 if (wantnormals || wanttangents)
4975 numvertices = model->surfmesh.num_vertices;
4977 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4980 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4981 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4983 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4984 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4985 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4986 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4987 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4992 // generate mesh cache
4993 numvertices = model->surfmesh.num_vertices;
4994 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4999 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5000 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5002 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5003 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5004 if (wantnormals || wanttangents)
5006 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5007 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5008 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5010 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5011 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5012 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5017 void R_AnimCache_CacheVisibleEntities(void)
5020 qboolean wantnormals = true;
5021 qboolean wanttangents = !r_showsurfaces.integer;
5023 switch(vid.renderpath)
5025 case RENDERPATH_GL20:
5026 case RENDERPATH_D3D9:
5027 case RENDERPATH_D3D10:
5028 case RENDERPATH_D3D11:
5029 case RENDERPATH_GLES2:
5031 case RENDERPATH_GL11:
5032 case RENDERPATH_GL13:
5033 case RENDERPATH_GLES1:
5034 wanttangents = false;
5036 case RENDERPATH_SOFT:
5040 if (r_shownormals.integer)
5041 wanttangents = wantnormals = true;
5043 // TODO: thread this
5044 // NOTE: R_PrepareRTLights() also caches entities
5046 for (i = 0;i < r_refdef.scene.numentities;i++)
5047 if (r_refdef.viewcache.entityvisible[i])
5048 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5051 //==================================================================================
5053 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5056 vec3_t eyemins, eyemaxs;
5057 vec3_t boxmins, boxmaxs;
5060 dp_model_t *model = r_refdef.scene.worldmodel;
5061 static vec3_t positions[] = {
5062 { 0.5f, 0.5f, 0.5f },
5063 { 0.0f, 0.0f, 0.0f },
5064 { 0.0f, 0.0f, 1.0f },
5065 { 0.0f, 1.0f, 0.0f },
5066 { 0.0f, 1.0f, 1.0f },
5067 { 1.0f, 0.0f, 0.0f },
5068 { 1.0f, 0.0f, 1.0f },
5069 { 1.0f, 1.0f, 0.0f },
5070 { 1.0f, 1.0f, 1.0f },
5073 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5077 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5078 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5081 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5084 // expand the eye box a little
5085 eyemins[0] = eye[0] - eyejitter;
5086 eyemaxs[0] = eye[0] + eyejitter;
5087 eyemins[1] = eye[1] - eyejitter;
5088 eyemaxs[1] = eye[1] + eyejitter;
5089 eyemins[2] = eye[2] - eyejitter;
5090 eyemaxs[2] = eye[2] + eyejitter;
5091 // expand the box a little
5092 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5093 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5094 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5095 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5096 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5097 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5099 // return true if eye overlaps enlarged box
5100 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5103 // try specific positions in the box first - note that these can be cached
5104 if (r_cullentities_trace_entityocclusion.integer)
5106 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5108 VectorCopy(eye, start);
5109 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5110 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5111 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5112 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5113 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5114 // not picky - if the trace ended anywhere in the box we're good
5115 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5119 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5122 // try various random positions
5123 for (i = 0; i < numsamples; i++)
5125 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5126 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5127 if (r_cullentities_trace_entityocclusion.integer)
5129 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5130 // not picky - if the trace ended anywhere in the box we're good
5131 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5134 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5142 static void R_View_UpdateEntityVisible (void)
5147 entity_render_t *ent;
5149 if (r_refdef.envmap || r_fb.water.hideplayer)
5150 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5151 else if (chase_active.integer || r_fb.water.renderingscene)
5152 renderimask = RENDER_VIEWMODEL;
5154 renderimask = RENDER_EXTERIORMODEL;
5155 if (!r_drawviewmodel.integer)
5156 renderimask |= RENDER_VIEWMODEL;
5157 if (!r_drawexteriormodel.integer)
5158 renderimask |= RENDER_EXTERIORMODEL;
5159 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5160 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5162 // worldmodel can check visibility
5163 for (i = 0;i < r_refdef.scene.numentities;i++)
5165 ent = r_refdef.scene.entities[i];
5166 if (!(ent->flags & renderimask))
5167 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)))
5168 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))
5169 r_refdef.viewcache.entityvisible[i] = true;
5174 // no worldmodel or it can't check visibility
5175 for (i = 0;i < r_refdef.scene.numentities;i++)
5177 ent = r_refdef.scene.entities[i];
5178 if (!(ent->flags & renderimask))
5179 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)))
5180 r_refdef.viewcache.entityvisible[i] = true;
5183 if (r_cullentities_trace.integer)
5185 for (i = 0;i < r_refdef.scene.numentities;i++)
5187 if (!r_refdef.viewcache.entityvisible[i])
5189 ent = r_refdef.scene.entities[i];
5190 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5192 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5193 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5194 ent->last_trace_visibility = realtime;
5195 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5196 r_refdef.viewcache.entityvisible[i] = 0;
5202 /// only used if skyrendermasked, and normally returns false
5203 static int R_DrawBrushModelsSky (void)
5206 entity_render_t *ent;
5209 for (i = 0;i < r_refdef.scene.numentities;i++)
5211 if (!r_refdef.viewcache.entityvisible[i])
5213 ent = r_refdef.scene.entities[i];
5214 if (!ent->model || !ent->model->DrawSky)
5216 ent->model->DrawSky(ent);
5222 static void R_DrawNoModel(entity_render_t *ent);
5223 static void R_DrawModels(void)
5226 entity_render_t *ent;
5228 for (i = 0;i < r_refdef.scene.numentities;i++)
5230 if (!r_refdef.viewcache.entityvisible[i])
5232 ent = r_refdef.scene.entities[i];
5233 r_refdef.stats[r_stat_entities]++;
5235 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5238 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5239 Con_Printf("R_DrawModels\n");
5240 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]);
5241 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);
5242 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);
5245 if (ent->model && ent->model->Draw != NULL)
5246 ent->model->Draw(ent);
5252 static void R_DrawModelsDepth(void)
5255 entity_render_t *ent;
5257 for (i = 0;i < r_refdef.scene.numentities;i++)
5259 if (!r_refdef.viewcache.entityvisible[i])
5261 ent = r_refdef.scene.entities[i];
5262 if (ent->model && ent->model->DrawDepth != NULL)
5263 ent->model->DrawDepth(ent);
5267 static void R_DrawModelsDebug(void)
5270 entity_render_t *ent;
5272 for (i = 0;i < r_refdef.scene.numentities;i++)
5274 if (!r_refdef.viewcache.entityvisible[i])
5276 ent = r_refdef.scene.entities[i];
5277 if (ent->model && ent->model->DrawDebug != NULL)
5278 ent->model->DrawDebug(ent);
5282 static void R_DrawModelsAddWaterPlanes(void)
5285 entity_render_t *ent;
5287 for (i = 0;i < r_refdef.scene.numentities;i++)
5289 if (!r_refdef.viewcache.entityvisible[i])
5291 ent = r_refdef.scene.entities[i];
5292 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5293 ent->model->DrawAddWaterPlanes(ent);
5297 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}};
5299 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5301 if (r_hdr_irisadaptation.integer)
5306 vec3_t diffusenormal;
5308 vec_t brightness = 0.0f;
5313 VectorCopy(r_refdef.view.forward, forward);
5314 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5316 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5317 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5318 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5319 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5320 d = DotProduct(forward, diffusenormal);
5321 brightness += VectorLength(ambient);
5323 brightness += d * VectorLength(diffuse);
5325 brightness *= 1.0f / c;
5326 brightness += 0.00001f; // make sure it's never zero
5327 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5328 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5329 current = r_hdr_irisadaptation_value.value;
5331 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5332 else if (current > goal)
5333 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5334 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5335 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5337 else if (r_hdr_irisadaptation_value.value != 1.0f)
5338 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5341 static void R_View_SetFrustum(const int *scissor)
5344 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5345 vec3_t forward, left, up, origin, v;
5349 // flipped x coordinates (because x points left here)
5350 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5351 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5353 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5354 switch(vid.renderpath)
5356 case RENDERPATH_D3D9:
5357 case RENDERPATH_D3D10:
5358 case RENDERPATH_D3D11:
5359 // non-flipped y coordinates
5360 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5361 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5363 case RENDERPATH_SOFT:
5364 case RENDERPATH_GL11:
5365 case RENDERPATH_GL13:
5366 case RENDERPATH_GL20:
5367 case RENDERPATH_GLES1:
5368 case RENDERPATH_GLES2:
5369 // non-flipped y coordinates
5370 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5371 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5376 // we can't trust r_refdef.view.forward and friends in reflected scenes
5377 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5380 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5381 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5382 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5383 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5384 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5385 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5386 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5387 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5388 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5389 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5390 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5391 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5395 zNear = r_refdef.nearclip;
5396 nudge = 1.0 - 1.0 / (1<<23);
5397 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5398 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5399 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5400 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5401 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5402 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5403 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5404 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5410 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5411 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5412 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5413 r_refdef.view.frustum[0].dist = m[15] - m[12];
5415 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5416 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5417 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5418 r_refdef.view.frustum[1].dist = m[15] + m[12];
5420 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5421 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5422 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5423 r_refdef.view.frustum[2].dist = m[15] - m[13];
5425 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5426 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5427 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5428 r_refdef.view.frustum[3].dist = m[15] + m[13];
5430 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5431 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5432 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5433 r_refdef.view.frustum[4].dist = m[15] - m[14];
5435 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5436 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5437 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5438 r_refdef.view.frustum[5].dist = m[15] + m[14];
5441 if (r_refdef.view.useperspective)
5443 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5444 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]);
5445 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]);
5446 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]);
5447 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]);
5449 // then the normals from the corners relative to origin
5450 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5451 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5452 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5453 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5455 // in a NORMAL view, forward cross left == up
5456 // in a REFLECTED view, forward cross left == down
5457 // so our cross products above need to be adjusted for a left handed coordinate system
5458 CrossProduct(forward, left, v);
5459 if(DotProduct(v, up) < 0)
5461 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5462 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5463 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5464 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5467 // Leaving those out was a mistake, those were in the old code, and they
5468 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5469 // I couldn't reproduce it after adding those normalizations. --blub
5470 VectorNormalize(r_refdef.view.frustum[0].normal);
5471 VectorNormalize(r_refdef.view.frustum[1].normal);
5472 VectorNormalize(r_refdef.view.frustum[2].normal);
5473 VectorNormalize(r_refdef.view.frustum[3].normal);
5475 // make the corners absolute
5476 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5477 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5478 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5479 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5482 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5484 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5485 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5486 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5487 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5488 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5492 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5493 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5494 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5495 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5496 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5497 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5498 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5499 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5500 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5501 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5503 r_refdef.view.numfrustumplanes = 5;
5505 if (r_refdef.view.useclipplane)
5507 r_refdef.view.numfrustumplanes = 6;
5508 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5511 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5512 PlaneClassify(r_refdef.view.frustum + i);
5514 // LordHavoc: note to all quake engine coders, Quake had a special case
5515 // for 90 degrees which assumed a square view (wrong), so I removed it,
5516 // Quake2 has it disabled as well.
5518 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5519 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5520 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5521 //PlaneClassify(&frustum[0]);
5523 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5524 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5525 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5526 //PlaneClassify(&frustum[1]);
5528 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5529 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5530 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5531 //PlaneClassify(&frustum[2]);
5533 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5534 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5535 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5536 //PlaneClassify(&frustum[3]);
5539 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5540 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5541 //PlaneClassify(&frustum[4]);
5544 static void R_View_UpdateWithScissor(const int *myscissor)
5546 R_Main_ResizeViewCache();
5547 R_View_SetFrustum(myscissor);
5548 R_View_WorldVisibility(r_refdef.view.useclipplane);
5549 R_View_UpdateEntityVisible();
5552 static void R_View_Update(void)
5554 R_Main_ResizeViewCache();
5555 R_View_SetFrustum(NULL);
5556 R_View_WorldVisibility(r_refdef.view.useclipplane);
5557 R_View_UpdateEntityVisible();
5560 float viewscalefpsadjusted = 1.0f;
5562 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5564 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5565 scale = bound(0.03125f, scale, 1.0f);
5566 *outwidth = (int)ceil(width * scale);
5567 *outheight = (int)ceil(height * scale);
5570 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5572 const float *customclipplane = NULL;
5574 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5575 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5577 // LordHavoc: couldn't figure out how to make this approach the
5578 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5579 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5580 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5581 dist = r_refdef.view.clipplane.dist;
5582 plane[0] = r_refdef.view.clipplane.normal[0];
5583 plane[1] = r_refdef.view.clipplane.normal[1];
5584 plane[2] = r_refdef.view.clipplane.normal[2];
5586 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5589 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5590 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5592 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5593 if (!r_refdef.view.useperspective)
5594 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);
5595 else if (vid.stencil && r_useinfinitefarclip.integer)
5596 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);
5598 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);
5599 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5600 R_SetViewport(&r_refdef.view.viewport);
5601 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5603 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5604 float screenplane[4];
5605 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5606 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5607 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5608 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5609 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5613 void R_EntityMatrix(const matrix4x4_t *matrix)
5615 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5617 gl_modelmatrixchanged = false;
5618 gl_modelmatrix = *matrix;
5619 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5620 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5621 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5622 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5624 switch(vid.renderpath)
5626 case RENDERPATH_D3D9:
5628 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5629 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5632 case RENDERPATH_D3D10:
5633 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5635 case RENDERPATH_D3D11:
5636 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5638 case RENDERPATH_GL11:
5639 case RENDERPATH_GL13:
5640 case RENDERPATH_GLES1:
5642 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5645 case RENDERPATH_SOFT:
5646 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5647 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5649 case RENDERPATH_GL20:
5650 case RENDERPATH_GLES2:
5651 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5652 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5658 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5660 r_viewport_t viewport;
5664 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5665 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);
5666 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5667 R_SetViewport(&viewport);
5668 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5669 GL_Color(1, 1, 1, 1);
5670 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5671 GL_BlendFunc(GL_ONE, GL_ZERO);
5672 GL_ScissorTest(false);
5673 GL_DepthMask(false);
5674 GL_DepthRange(0, 1);
5675 GL_DepthTest(false);
5676 GL_DepthFunc(GL_LEQUAL);
5677 R_EntityMatrix(&identitymatrix);
5678 R_Mesh_ResetTextureState();
5679 GL_PolygonOffset(0, 0);
5680 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5681 switch(vid.renderpath)
5683 case RENDERPATH_GL11:
5684 case RENDERPATH_GL13:
5685 case RENDERPATH_GL20:
5686 case RENDERPATH_GLES1:
5687 case RENDERPATH_GLES2:
5688 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5690 case RENDERPATH_D3D9:
5691 case RENDERPATH_D3D10:
5692 case RENDERPATH_D3D11:
5693 case RENDERPATH_SOFT:
5696 GL_CullFace(GL_NONE);
5701 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5705 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5708 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5712 R_SetupView(true, fbo, depthtexture, colortexture);
5713 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5714 GL_Color(1, 1, 1, 1);
5715 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5716 GL_BlendFunc(GL_ONE, GL_ZERO);
5717 GL_ScissorTest(true);
5719 GL_DepthRange(0, 1);
5721 GL_DepthFunc(GL_LEQUAL);
5722 R_EntityMatrix(&identitymatrix);
5723 R_Mesh_ResetTextureState();
5724 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5725 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5726 switch(vid.renderpath)
5728 case RENDERPATH_GL11:
5729 case RENDERPATH_GL13:
5730 case RENDERPATH_GL20:
5731 case RENDERPATH_GLES1:
5732 case RENDERPATH_GLES2:
5733 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5735 case RENDERPATH_D3D9:
5736 case RENDERPATH_D3D10:
5737 case RENDERPATH_D3D11:
5738 case RENDERPATH_SOFT:
5741 GL_CullFace(r_refdef.view.cullface_back);
5746 R_RenderView_UpdateViewVectors
5749 void R_RenderView_UpdateViewVectors(void)
5751 // break apart the view matrix into vectors for various purposes
5752 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5753 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5754 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5755 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5756 // make an inverted copy of the view matrix for tracking sprites
5757 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5760 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5761 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5763 static void R_Water_StartFrame(void)
5766 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5767 r_waterstate_waterplane_t *p;
5768 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;
5770 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5773 switch(vid.renderpath)
5775 case RENDERPATH_GL20:
5776 case RENDERPATH_D3D9:
5777 case RENDERPATH_D3D10:
5778 case RENDERPATH_D3D11:
5779 case RENDERPATH_SOFT:
5780 case RENDERPATH_GLES2:
5782 case RENDERPATH_GL11:
5783 case RENDERPATH_GL13:
5784 case RENDERPATH_GLES1:
5788 // set waterwidth and waterheight to the water resolution that will be
5789 // used (often less than the screen resolution for faster rendering)
5790 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5792 // calculate desired texture sizes
5793 // can't use water if the card does not support the texture size
5794 if (!r_water.integer || r_showsurfaces.integer)
5795 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5796 else if (vid.support.arb_texture_non_power_of_two)
5798 texturewidth = waterwidth;
5799 textureheight = waterheight;
5800 camerawidth = waterwidth;
5801 cameraheight = waterheight;
5805 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5806 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5807 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5808 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5811 // allocate textures as needed
5812 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))
5814 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5815 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5817 if (p->texture_refraction)
5818 R_FreeTexture(p->texture_refraction);
5819 p->texture_refraction = NULL;
5820 if (p->fbo_refraction)
5821 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5822 p->fbo_refraction = 0;
5823 if (p->texture_reflection)
5824 R_FreeTexture(p->texture_reflection);
5825 p->texture_reflection = NULL;
5826 if (p->fbo_reflection)
5827 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5828 p->fbo_reflection = 0;
5829 if (p->texture_camera)
5830 R_FreeTexture(p->texture_camera);
5831 p->texture_camera = NULL;
5833 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5836 memset(&r_fb.water, 0, sizeof(r_fb.water));
5837 r_fb.water.texturewidth = texturewidth;
5838 r_fb.water.textureheight = textureheight;
5839 r_fb.water.camerawidth = camerawidth;
5840 r_fb.water.cameraheight = cameraheight;
5843 if (r_fb.water.texturewidth)
5845 int scaledwidth, scaledheight;
5847 r_fb.water.enabled = true;
5849 // water resolution is usually reduced
5850 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5851 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5852 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5854 // set up variables that will be used in shader setup
5855 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5856 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5857 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5858 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5861 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5862 r_fb.water.numwaterplanes = 0;
5865 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5867 int planeindex, bestplaneindex, vertexindex;
5868 vec3_t mins, maxs, normal, center, v, n;
5869 vec_t planescore, bestplanescore;
5871 r_waterstate_waterplane_t *p;
5872 texture_t *t = R_GetCurrentTexture(surface->texture);
5874 rsurface.texture = t;
5875 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5876 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5877 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5879 // average the vertex normals, find the surface bounds (after deformvertexes)
5880 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5881 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5882 VectorCopy(n, normal);
5883 VectorCopy(v, mins);
5884 VectorCopy(v, maxs);
5885 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5887 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5888 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5889 VectorAdd(normal, n, normal);
5890 mins[0] = min(mins[0], v[0]);
5891 mins[1] = min(mins[1], v[1]);
5892 mins[2] = min(mins[2], v[2]);
5893 maxs[0] = max(maxs[0], v[0]);
5894 maxs[1] = max(maxs[1], v[1]);
5895 maxs[2] = max(maxs[2], v[2]);
5897 VectorNormalize(normal);
5898 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5900 VectorCopy(normal, plane.normal);
5901 VectorNormalize(plane.normal);
5902 plane.dist = DotProduct(center, plane.normal);
5903 PlaneClassify(&plane);
5904 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5906 // skip backfaces (except if nocullface is set)
5907 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5909 VectorNegate(plane.normal, plane.normal);
5911 PlaneClassify(&plane);
5915 // find a matching plane if there is one
5916 bestplaneindex = -1;
5917 bestplanescore = 1048576.0f;
5918 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5920 if(p->camera_entity == t->camera_entity)
5922 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5923 if (bestplaneindex < 0 || bestplanescore > planescore)
5925 bestplaneindex = planeindex;
5926 bestplanescore = planescore;
5930 planeindex = bestplaneindex;
5932 // if this surface does not fit any known plane rendered this frame, add one
5933 if (planeindex < 0 || bestplanescore > 0.001f)
5935 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5937 // store the new plane
5938 planeindex = r_fb.water.numwaterplanes++;
5939 p = r_fb.water.waterplanes + planeindex;
5941 // clear materialflags and pvs
5942 p->materialflags = 0;
5943 p->pvsvalid = false;
5944 p->camera_entity = t->camera_entity;
5945 VectorCopy(mins, p->mins);
5946 VectorCopy(maxs, p->maxs);
5950 // We're totally screwed.
5956 // merge mins/maxs when we're adding this surface to the plane
5957 p = r_fb.water.waterplanes + planeindex;
5958 p->mins[0] = min(p->mins[0], mins[0]);
5959 p->mins[1] = min(p->mins[1], mins[1]);
5960 p->mins[2] = min(p->mins[2], mins[2]);
5961 p->maxs[0] = max(p->maxs[0], maxs[0]);
5962 p->maxs[1] = max(p->maxs[1], maxs[1]);
5963 p->maxs[2] = max(p->maxs[2], maxs[2]);
5965 // merge this surface's materialflags into the waterplane
5966 p->materialflags |= t->currentmaterialflags;
5967 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5969 // merge this surface's PVS into the waterplane
5970 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5971 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5973 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5979 extern cvar_t r_drawparticles;
5980 extern cvar_t r_drawdecals;
5982 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5985 r_refdef_view_t originalview;
5986 r_refdef_view_t myview;
5987 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;
5988 r_waterstate_waterplane_t *p;
5990 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;
5993 originalview = r_refdef.view;
5995 // lowquality hack, temporarily shut down some cvars and restore afterwards
5996 qualityreduction = r_water_lowquality.integer;
5997 if (qualityreduction > 0)
5999 if (qualityreduction >= 1)
6001 old_r_shadows = r_shadows.integer;
6002 old_r_worldrtlight = r_shadow_realtime_world.integer;
6003 old_r_dlight = r_shadow_realtime_dlight.integer;
6004 Cvar_SetValueQuick(&r_shadows, 0);
6005 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6006 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6008 if (qualityreduction >= 2)
6010 old_r_dynamic = r_dynamic.integer;
6011 old_r_particles = r_drawparticles.integer;
6012 old_r_decals = r_drawdecals.integer;
6013 Cvar_SetValueQuick(&r_dynamic, 0);
6014 Cvar_SetValueQuick(&r_drawparticles, 0);
6015 Cvar_SetValueQuick(&r_drawdecals, 0);
6019 // make sure enough textures are allocated
6020 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6022 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6024 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6026 if (!p->texture_refraction)
6027 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);
6028 if (!p->texture_refraction)
6032 if (r_fb.water.depthtexture == NULL)
6033 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6034 if (p->fbo_refraction == 0)
6035 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6038 else if (p->materialflags & MATERIALFLAG_CAMERA)
6040 if (!p->texture_camera)
6041 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);
6042 if (!p->texture_camera)
6046 if (r_fb.water.depthtexture == NULL)
6047 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6048 if (p->fbo_camera == 0)
6049 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6053 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6055 if (!p->texture_reflection)
6056 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);
6057 if (!p->texture_reflection)
6061 if (r_fb.water.depthtexture == NULL)
6062 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6063 if (p->fbo_reflection == 0)
6064 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6070 r_refdef.view = originalview;
6071 r_refdef.view.showdebug = false;
6072 r_refdef.view.width = r_fb.water.waterwidth;
6073 r_refdef.view.height = r_fb.water.waterheight;
6074 r_refdef.view.useclipplane = true;
6075 myview = r_refdef.view;
6076 r_fb.water.renderingscene = true;
6077 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6079 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6081 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6083 r_refdef.view = myview;
6084 if(r_water_scissormode.integer)
6086 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6087 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6088 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6091 // render reflected scene and copy into texture
6092 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6093 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6094 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6095 r_refdef.view.clipplane = p->plane;
6096 // reverse the cullface settings for this render
6097 r_refdef.view.cullface_front = GL_FRONT;
6098 r_refdef.view.cullface_back = GL_BACK;
6099 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6101 r_refdef.view.usecustompvs = true;
6103 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6105 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6108 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6109 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6110 R_ClearScreen(r_refdef.fogenabled);
6111 if(r_water_scissormode.integer & 2)
6112 R_View_UpdateWithScissor(myscissor);
6115 R_AnimCache_CacheVisibleEntities();
6116 if(r_water_scissormode.integer & 1)
6117 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6118 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6120 if (!p->fbo_reflection)
6121 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);
6122 r_fb.water.hideplayer = false;
6125 // render the normal view scene and copy into texture
6126 // (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)
6127 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6129 r_refdef.view = myview;
6130 if(r_water_scissormode.integer)
6132 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6133 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6134 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6137 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6139 r_refdef.view.clipplane = p->plane;
6140 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6141 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6143 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6145 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6146 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6147 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6148 R_RenderView_UpdateViewVectors();
6149 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6151 r_refdef.view.usecustompvs = true;
6152 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);
6156 PlaneClassify(&r_refdef.view.clipplane);
6158 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6159 R_ClearScreen(r_refdef.fogenabled);
6160 if(r_water_scissormode.integer & 2)
6161 R_View_UpdateWithScissor(myscissor);
6164 R_AnimCache_CacheVisibleEntities();
6165 if(r_water_scissormode.integer & 1)
6166 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6167 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6169 if (!p->fbo_refraction)
6170 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);
6171 r_fb.water.hideplayer = false;
6173 else if (p->materialflags & MATERIALFLAG_CAMERA)
6175 r_refdef.view = myview;
6177 r_refdef.view.clipplane = p->plane;
6178 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6179 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6181 r_refdef.view.width = r_fb.water.camerawidth;
6182 r_refdef.view.height = r_fb.water.cameraheight;
6183 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6184 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6185 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6186 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6188 if(p->camera_entity)
6190 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6191 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6194 // note: all of the view is used for displaying... so
6195 // there is no use in scissoring
6197 // reverse the cullface settings for this render
6198 r_refdef.view.cullface_front = GL_FRONT;
6199 r_refdef.view.cullface_back = GL_BACK;
6200 // also reverse the view matrix
6201 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
6202 R_RenderView_UpdateViewVectors();
6203 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6205 r_refdef.view.usecustompvs = true;
6206 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);
6209 // camera needs no clipplane
6210 r_refdef.view.useclipplane = false;
6212 PlaneClassify(&r_refdef.view.clipplane);
6214 r_fb.water.hideplayer = false;
6216 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6217 R_ClearScreen(r_refdef.fogenabled);
6219 R_AnimCache_CacheVisibleEntities();
6220 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6223 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);
6224 r_fb.water.hideplayer = false;
6228 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6229 r_fb.water.renderingscene = false;
6230 r_refdef.view = originalview;
6231 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6232 if (!r_fb.water.depthtexture)
6233 R_ClearScreen(r_refdef.fogenabled);
6235 R_AnimCache_CacheVisibleEntities();
6238 r_refdef.view = originalview;
6239 r_fb.water.renderingscene = false;
6240 Cvar_SetValueQuick(&r_water, 0);
6241 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6243 // lowquality hack, restore cvars
6244 if (qualityreduction > 0)
6246 if (qualityreduction >= 1)
6248 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6249 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6250 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6252 if (qualityreduction >= 2)
6254 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6255 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6256 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6261 static void R_Bloom_StartFrame(void)
6264 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6265 int viewwidth, viewheight;
6266 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6267 textype_t textype = TEXTYPE_COLORBUFFER;
6269 switch (vid.renderpath)
6271 case RENDERPATH_GL20:
6272 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6273 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6275 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6276 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6279 case RENDERPATH_GL11:
6280 case RENDERPATH_GL13:
6281 case RENDERPATH_GLES1:
6282 return; // don't bother
6283 case RENDERPATH_GLES2:
6284 case RENDERPATH_D3D9:
6285 case RENDERPATH_D3D10:
6286 case RENDERPATH_D3D11:
6287 r_fb.usedepthtextures = false;
6289 case RENDERPATH_SOFT:
6290 r_fb.usedepthtextures = true;
6294 if (r_viewscale_fpsscaling.integer)
6296 double actualframetime;
6297 double targetframetime;
6299 actualframetime = r_refdef.lastdrawscreentime;
6300 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6301 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6302 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6303 if (r_viewscale_fpsscaling_stepsize.value > 0)
6304 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6305 viewscalefpsadjusted += adjust;
6306 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6309 viewscalefpsadjusted = 1.0f;
6311 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6313 switch(vid.renderpath)
6315 case RENDERPATH_GL20:
6316 case RENDERPATH_D3D9:
6317 case RENDERPATH_D3D10:
6318 case RENDERPATH_D3D11:
6319 case RENDERPATH_SOFT:
6320 case RENDERPATH_GLES2:
6322 case RENDERPATH_GL11:
6323 case RENDERPATH_GL13:
6324 case RENDERPATH_GLES1:
6328 // set bloomwidth and bloomheight to the bloom resolution that will be
6329 // used (often less than the screen resolution for faster rendering)
6330 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6331 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6332 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6333 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6334 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6336 // calculate desired texture sizes
6337 if (vid.support.arb_texture_non_power_of_two)
6339 screentexturewidth = vid.width;
6340 screentextureheight = vid.height;
6341 bloomtexturewidth = r_fb.bloomwidth;
6342 bloomtextureheight = r_fb.bloomheight;
6346 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6347 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6348 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6349 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6352 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))
6354 Cvar_SetValueQuick(&r_bloom, 0);
6355 Cvar_SetValueQuick(&r_motionblur, 0);
6356 Cvar_SetValueQuick(&r_damageblur, 0);
6359 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || !vid_gammatables_trivial)
6361 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6363 && r_viewscale.value == 1.0f
6364 && !r_viewscale_fpsscaling.integer)
6365 screentexturewidth = screentextureheight = 0;
6366 if (!r_bloom.integer)
6367 bloomtexturewidth = bloomtextureheight = 0;
6369 // allocate textures as needed
6370 if (r_fb.screentexturewidth != screentexturewidth
6371 || r_fb.screentextureheight != screentextureheight
6372 || r_fb.bloomtexturewidth != bloomtexturewidth
6373 || r_fb.bloomtextureheight != bloomtextureheight
6374 || r_fb.textype != textype
6375 || useviewfbo != (r_fb.fbo != 0))
6377 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6379 if (r_fb.bloomtexture[i])
6380 R_FreeTexture(r_fb.bloomtexture[i]);
6381 r_fb.bloomtexture[i] = NULL;
6383 if (r_fb.bloomfbo[i])
6384 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6385 r_fb.bloomfbo[i] = 0;
6389 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6392 if (r_fb.colortexture)
6393 R_FreeTexture(r_fb.colortexture);
6394 r_fb.colortexture = NULL;
6396 if (r_fb.depthtexture)
6397 R_FreeTexture(r_fb.depthtexture);
6398 r_fb.depthtexture = NULL;
6400 if (r_fb.ghosttexture)
6401 R_FreeTexture(r_fb.ghosttexture);
6402 r_fb.ghosttexture = NULL;
6404 r_fb.screentexturewidth = screentexturewidth;
6405 r_fb.screentextureheight = screentextureheight;
6406 r_fb.bloomtexturewidth = bloomtexturewidth;
6407 r_fb.bloomtextureheight = bloomtextureheight;
6408 r_fb.textype = textype;
6410 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6412 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6413 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);
6414 r_fb.ghosttexture_valid = false;
6415 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);
6418 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6419 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6420 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6424 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6426 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6428 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);
6430 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6435 // bloom texture is a different resolution
6436 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6437 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6438 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6439 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6440 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6442 // set up a texcoord array for the full resolution screen image
6443 // (we have to keep this around to copy back during final render)
6444 r_fb.screentexcoord2f[0] = 0;
6445 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6446 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6447 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6448 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6449 r_fb.screentexcoord2f[5] = 0;
6450 r_fb.screentexcoord2f[6] = 0;
6451 r_fb.screentexcoord2f[7] = 0;
6455 for (i = 1;i < 8;i += 2)
6457 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6461 // set up a texcoord array for the reduced resolution bloom image
6462 // (which will be additive blended over the screen image)
6463 r_fb.bloomtexcoord2f[0] = 0;
6464 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6465 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6466 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6467 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6468 r_fb.bloomtexcoord2f[5] = 0;
6469 r_fb.bloomtexcoord2f[6] = 0;
6470 r_fb.bloomtexcoord2f[7] = 0;
6472 switch(vid.renderpath)
6474 case RENDERPATH_GL11:
6475 case RENDERPATH_GL13:
6476 case RENDERPATH_GL20:
6477 case RENDERPATH_SOFT:
6478 case RENDERPATH_GLES1:
6479 case RENDERPATH_GLES2:
6481 case RENDERPATH_D3D9:
6482 case RENDERPATH_D3D10:
6483 case RENDERPATH_D3D11:
6484 for (i = 0;i < 4;i++)
6486 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6487 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6488 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6489 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6494 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6497 r_refdef.view.clear = true;
6500 static void R_Bloom_MakeTexture(void)
6503 float xoffset, yoffset, r, brighten;
6505 float colorscale = r_bloom_colorscale.value;
6507 r_refdef.stats[r_stat_bloom]++;
6510 // this copy is unnecessary since it happens in R_BlendView already
6513 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);
6514 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6518 // scale down screen texture to the bloom texture size
6520 r_fb.bloomindex = 0;
6521 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6522 R_SetViewport(&r_fb.bloomviewport);
6523 GL_CullFace(GL_NONE);
6524 GL_DepthTest(false);
6525 GL_BlendFunc(GL_ONE, GL_ZERO);
6526 GL_Color(colorscale, colorscale, colorscale, 1);
6527 // 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...
6528 switch(vid.renderpath)
6530 case RENDERPATH_GL11:
6531 case RENDERPATH_GL13:
6532 case RENDERPATH_GL20:
6533 case RENDERPATH_GLES1:
6534 case RENDERPATH_GLES2:
6535 case RENDERPATH_SOFT:
6536 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6538 case RENDERPATH_D3D9:
6539 case RENDERPATH_D3D10:
6540 case RENDERPATH_D3D11:
6541 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6544 // TODO: do boxfilter scale-down in shader?
6545 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6546 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6547 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6549 // we now have a properly scaled bloom image
6550 if (!r_fb.bloomfbo[r_fb.bloomindex])
6552 // copy it into the bloom texture
6553 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);
6554 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6557 // multiply bloom image by itself as many times as desired
6558 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6560 intex = r_fb.bloomtexture[r_fb.bloomindex];
6561 r_fb.bloomindex ^= 1;
6562 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6564 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6565 if (!r_fb.bloomfbo[r_fb.bloomindex])
6567 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6568 GL_Color(r,r,r,1); // apply fix factor
6573 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6574 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6575 GL_Color(1,1,1,1); // no fix factor supported here
6577 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6578 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6579 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6580 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6582 if (!r_fb.bloomfbo[r_fb.bloomindex])
6584 // copy the darkened image to a texture
6585 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);
6586 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6590 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6591 brighten = r_bloom_brighten.value;
6592 brighten = sqrt(brighten);
6594 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6596 for (dir = 0;dir < 2;dir++)
6598 intex = r_fb.bloomtexture[r_fb.bloomindex];
6599 r_fb.bloomindex ^= 1;
6600 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6601 // blend on at multiple vertical offsets to achieve a vertical blur
6602 // TODO: do offset blends using GLSL
6603 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6604 GL_BlendFunc(GL_ONE, GL_ZERO);
6605 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6606 for (x = -range;x <= range;x++)
6608 if (!dir){xoffset = 0;yoffset = x;}
6609 else {xoffset = x;yoffset = 0;}
6610 xoffset /= (float)r_fb.bloomtexturewidth;
6611 yoffset /= (float)r_fb.bloomtextureheight;
6612 // compute a texcoord array with the specified x and y offset
6613 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6614 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6615 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6616 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6617 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6618 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6619 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6620 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6621 // this r value looks like a 'dot' particle, fading sharply to
6622 // black at the edges
6623 // (probably not realistic but looks good enough)
6624 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6625 //r = brighten/(range*2+1);
6626 r = brighten / (range * 2 + 1);
6628 r *= (1 - x*x/(float)(range*range));
6629 GL_Color(r, r, r, 1);
6630 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6631 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6632 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6633 GL_BlendFunc(GL_ONE, GL_ONE);
6636 if (!r_fb.bloomfbo[r_fb.bloomindex])
6638 // copy the vertically or horizontally blurred bloom view to a texture
6639 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);
6640 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6645 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6647 dpuint64 permutation;
6648 float uservecs[4][4];
6650 R_EntityMatrix(&identitymatrix);
6652 switch (vid.renderpath)
6654 case RENDERPATH_GL20:
6655 case RENDERPATH_D3D9:
6656 case RENDERPATH_D3D10:
6657 case RENDERPATH_D3D11:
6658 case RENDERPATH_SOFT:
6659 case RENDERPATH_GLES2:
6661 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6662 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6663 | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6664 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6665 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6667 if (r_fb.colortexture)
6671 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);
6672 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6675 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6677 // declare variables
6678 float blur_factor, blur_mouseaccel, blur_velocity;
6679 static float blur_average;
6680 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6682 // set a goal for the factoring
6683 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6684 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6685 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6686 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6687 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6688 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6690 // from the goal, pick an averaged value between goal and last value
6691 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6692 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6694 // enforce minimum amount of blur
6695 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6697 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6699 // calculate values into a standard alpha
6700 cl.motionbluralpha = 1 - exp(-
6702 (r_motionblur.value * blur_factor / 80)
6704 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6707 max(0.0001, cl.time - cl.oldtime) // fps independent
6710 // randomization for the blur value to combat persistent ghosting
6711 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6712 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6715 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6716 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6718 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6719 GL_Color(1, 1, 1, cl.motionbluralpha);
6720 switch(vid.renderpath)
6722 case RENDERPATH_GL11:
6723 case RENDERPATH_GL13:
6724 case RENDERPATH_GL20:
6725 case RENDERPATH_GLES1:
6726 case RENDERPATH_GLES2:
6727 case RENDERPATH_SOFT:
6728 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6730 case RENDERPATH_D3D9:
6731 case RENDERPATH_D3D10:
6732 case RENDERPATH_D3D11:
6733 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6736 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6737 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6738 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6741 // updates old view angles for next pass
6742 VectorCopy(cl.viewangles, blur_oldangles);
6744 // copy view into the ghost texture
6745 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);
6746 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6747 r_fb.ghosttexture_valid = true;
6752 // no r_fb.colortexture means we're rendering to the real fb
6753 // we may still have to do view tint...
6754 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6756 // apply a color tint to the whole view
6757 R_ResetViewRendering2D(0, NULL, NULL);
6758 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6759 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6760 R_SetupShader_Generic_NoTexture(false, true);
6761 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6762 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6764 break; // no screen processing, no bloom, skip it
6767 if (r_fb.bloomtexture[0])
6769 // make the bloom texture
6770 R_Bloom_MakeTexture();
6773 #if _MSC_VER >= 1400
6774 #define sscanf sscanf_s
6776 memset(uservecs, 0, sizeof(uservecs));
6777 if (r_glsl_postprocess_uservec1_enable.integer)
6778 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6779 if (r_glsl_postprocess_uservec2_enable.integer)
6780 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6781 if (r_glsl_postprocess_uservec3_enable.integer)
6782 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6783 if (r_glsl_postprocess_uservec4_enable.integer)
6784 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6786 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6787 GL_Color(1, 1, 1, 1);
6788 GL_BlendFunc(GL_ONE, GL_ZERO);
6790 switch(vid.renderpath)
6792 case RENDERPATH_GL20:
6793 case RENDERPATH_GLES2:
6794 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6795 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6796 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6797 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6798 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6799 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]);
6800 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6801 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]);
6802 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]);
6803 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]);
6804 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]);
6805 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6806 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6807 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);
6809 case RENDERPATH_D3D9:
6811 // 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...
6812 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6813 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6814 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6815 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6816 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6817 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6818 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6819 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6820 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6821 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6822 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6823 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6824 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6825 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6828 case RENDERPATH_D3D10:
6829 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6831 case RENDERPATH_D3D11:
6832 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6834 case RENDERPATH_SOFT:
6835 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6836 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6837 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6838 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6839 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6840 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6841 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6842 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6843 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6844 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6845 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6846 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6847 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6848 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6853 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6854 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6856 case RENDERPATH_GL11:
6857 case RENDERPATH_GL13:
6858 case RENDERPATH_GLES1:
6859 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6861 // apply a color tint to the whole view
6862 R_ResetViewRendering2D(0, NULL, NULL);
6863 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6864 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6865 R_SetupShader_Generic_NoTexture(false, true);
6866 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6867 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6873 matrix4x4_t r_waterscrollmatrix;
6875 void R_UpdateFog(void)
6878 if (gamemode == GAME_NEHAHRA)
6880 if (gl_fogenable.integer)
6882 r_refdef.oldgl_fogenable = true;
6883 r_refdef.fog_density = gl_fogdensity.value;
6884 r_refdef.fog_red = gl_fogred.value;
6885 r_refdef.fog_green = gl_foggreen.value;
6886 r_refdef.fog_blue = gl_fogblue.value;
6887 r_refdef.fog_alpha = 1;
6888 r_refdef.fog_start = 0;
6889 r_refdef.fog_end = gl_skyclip.value;
6890 r_refdef.fog_height = 1<<30;
6891 r_refdef.fog_fadedepth = 128;
6893 else if (r_refdef.oldgl_fogenable)
6895 r_refdef.oldgl_fogenable = false;
6896 r_refdef.fog_density = 0;
6897 r_refdef.fog_red = 0;
6898 r_refdef.fog_green = 0;
6899 r_refdef.fog_blue = 0;
6900 r_refdef.fog_alpha = 0;
6901 r_refdef.fog_start = 0;
6902 r_refdef.fog_end = 0;
6903 r_refdef.fog_height = 1<<30;
6904 r_refdef.fog_fadedepth = 128;
6909 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6910 r_refdef.fog_start = max(0, r_refdef.fog_start);
6911 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6913 if (r_refdef.fog_density && r_drawfog.integer)
6915 r_refdef.fogenabled = true;
6916 // this is the point where the fog reaches 0.9986 alpha, which we
6917 // consider a good enough cutoff point for the texture
6918 // (0.9986 * 256 == 255.6)
6919 if (r_fog_exp2.integer)
6920 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6922 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6923 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6924 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6925 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6926 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6927 R_BuildFogHeightTexture();
6928 // fog color was already set
6929 // update the fog texture
6930 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)
6931 R_BuildFogTexture();
6932 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6933 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6936 r_refdef.fogenabled = false;
6939 if (r_refdef.fog_density)
6941 r_refdef.fogcolor[0] = r_refdef.fog_red;
6942 r_refdef.fogcolor[1] = r_refdef.fog_green;
6943 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6945 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6946 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6947 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6948 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6952 VectorCopy(r_refdef.fogcolor, fogvec);
6953 // color.rgb *= ContrastBoost * SceneBrightness;
6954 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6955 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6956 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6957 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6962 void R_UpdateVariables(void)
6966 r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6968 r_refdef.farclip = r_farclip_base.value;
6969 if (r_refdef.scene.worldmodel)
6970 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6971 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6973 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6974 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6975 r_refdef.polygonfactor = 0;
6976 r_refdef.polygonoffset = 0;
6977 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6978 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6980 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6981 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6982 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6983 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6984 r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6985 if (FAKELIGHT_ENABLED)
6987 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6989 else if (r_refdef.scene.worldmodel)
6991 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6993 if (r_showsurfaces.integer)
6995 r_refdef.scene.rtworld = false;
6996 r_refdef.scene.rtworldshadows = false;
6997 r_refdef.scene.rtdlight = false;
6998 r_refdef.scene.rtdlightshadows = false;
6999 r_refdef.scene.lightmapintensity = 0;
7002 r_gpuskeletal = false;
7003 switch(vid.renderpath)
7005 case RENDERPATH_GL20:
7006 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7007 case RENDERPATH_D3D9:
7008 case RENDERPATH_D3D10:
7009 case RENDERPATH_D3D11:
7010 case RENDERPATH_SOFT:
7011 case RENDERPATH_GLES2:
7012 if(!vid_gammatables_trivial)
7014 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7016 // build GLSL gamma texture
7017 #define RAMPWIDTH 256
7018 unsigned short ramp[RAMPWIDTH * 3];
7019 unsigned char rampbgr[RAMPWIDTH][4];
7022 r_texture_gammaramps_serial = vid_gammatables_serial;
7024 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7025 for(i = 0; i < RAMPWIDTH; ++i)
7027 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7028 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7029 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7032 if (r_texture_gammaramps)
7034 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7038 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7044 // remove GLSL gamma texture
7047 case RENDERPATH_GL11:
7048 case RENDERPATH_GL13:
7049 case RENDERPATH_GLES1:
7054 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7055 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7061 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7062 if( scenetype != r_currentscenetype ) {
7063 // store the old scenetype
7064 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7065 r_currentscenetype = scenetype;
7066 // move in the new scene
7067 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7076 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7078 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7079 if( scenetype == r_currentscenetype ) {
7080 return &r_refdef.scene;
7082 return &r_scenes_store[ scenetype ];
7086 static int R_SortEntities_Compare(const void *ap, const void *bp)
7088 const entity_render_t *a = *(const entity_render_t **)ap;
7089 const entity_render_t *b = *(const entity_render_t **)bp;
7092 if(a->model < b->model)
7094 if(a->model > b->model)
7098 // TODO possibly calculate the REAL skinnum here first using
7100 if(a->skinnum < b->skinnum)
7102 if(a->skinnum > b->skinnum)
7105 // everything we compared is equal
7108 static void R_SortEntities(void)
7110 // below or equal 2 ents, sorting never gains anything
7111 if(r_refdef.scene.numentities <= 2)
7114 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7122 int dpsoftrast_test;
7123 extern cvar_t r_shadow_bouncegrid;
7124 void R_RenderView(void)
7126 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7128 rtexture_t *depthtexture;
7129 rtexture_t *colortexture;
7131 dpsoftrast_test = r_test.integer;
7133 if (r_timereport_active)
7134 R_TimeReport("start");
7135 r_textureframe++; // used only by R_GetCurrentTexture
7136 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7138 if(R_CompileShader_CheckStaticParms())
7141 if (!r_drawentities.integer)
7142 r_refdef.scene.numentities = 0;
7143 else if (r_sortentities.integer)
7146 R_AnimCache_ClearCache();
7148 /* adjust for stereo display */
7149 if(R_Stereo_Active())
7151 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);
7152 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7155 if (r_refdef.view.isoverlay)
7157 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7158 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7159 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7160 R_TimeReport("depthclear");
7162 r_refdef.view.showdebug = false;
7164 r_fb.water.enabled = false;
7165 r_fb.water.numwaterplanes = 0;
7167 R_RenderScene(0, NULL, NULL);
7169 r_refdef.view.matrix = originalmatrix;
7175 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7177 r_refdef.view.matrix = originalmatrix;
7181 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7183 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7184 // in sRGB fallback, behave similar to true sRGB: convert this
7185 // value from linear to sRGB
7186 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7188 R_RenderView_UpdateViewVectors();
7190 R_Shadow_UpdateWorldLightSelection();
7192 R_Bloom_StartFrame();
7194 // apply bloom brightness offset
7195 if(r_fb.bloomtexture[0])
7196 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7198 R_Water_StartFrame();
7200 // now we probably have an fbo to render into
7202 depthtexture = r_fb.depthtexture;
7203 colortexture = r_fb.colortexture;
7206 if (r_timereport_active)
7207 R_TimeReport("viewsetup");
7209 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7211 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7213 R_ClearScreen(r_refdef.fogenabled);
7214 if (r_timereport_active)
7215 R_TimeReport("viewclear");
7217 r_refdef.view.clear = true;
7219 r_refdef.view.showdebug = true;
7222 if (r_timereport_active)
7223 R_TimeReport("visibility");
7225 R_AnimCache_CacheVisibleEntities();
7226 if (r_timereport_active)
7227 R_TimeReport("animcache");
7229 R_Shadow_UpdateBounceGridTexture();
7230 if (r_timereport_active && r_shadow_bouncegrid.integer)
7231 R_TimeReport("bouncegrid");
7233 r_fb.water.numwaterplanes = 0;
7234 if (r_fb.water.enabled)
7235 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7237 R_RenderScene(fbo, depthtexture, colortexture);
7238 r_fb.water.numwaterplanes = 0;
7240 R_BlendView(fbo, depthtexture, colortexture);
7241 if (r_timereport_active)
7242 R_TimeReport("blendview");
7244 GL_Scissor(0, 0, vid.width, vid.height);
7245 GL_ScissorTest(false);
7247 r_refdef.view.matrix = originalmatrix;
7252 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7254 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7256 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7257 if (r_timereport_active)
7258 R_TimeReport("waterworld");
7261 // don't let sound skip if going slow
7262 if (r_refdef.scene.extraupdate)
7265 R_DrawModelsAddWaterPlanes();
7266 if (r_timereport_active)
7267 R_TimeReport("watermodels");
7269 if (r_fb.water.numwaterplanes)
7271 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7272 if (r_timereport_active)
7273 R_TimeReport("waterscenes");
7277 extern cvar_t cl_locs_show;
7278 static void R_DrawLocs(void);
7279 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7280 static void R_DrawModelDecals(void);
7281 extern cvar_t cl_decals_newsystem;
7282 extern qboolean r_shadow_usingdeferredprepass;
7283 extern int r_shadow_shadowmapatlas_modelshadows_size;
7284 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7286 qboolean shadowmapping = false;
7288 if (r_timereport_active)
7289 R_TimeReport("beginscene");
7291 r_refdef.stats[r_stat_renders]++;
7295 // don't let sound skip if going slow
7296 if (r_refdef.scene.extraupdate)
7299 R_MeshQueue_BeginScene();
7303 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);
7305 if (r_timereport_active)
7306 R_TimeReport("skystartframe");
7308 if (cl.csqc_vidvars.drawworld)
7310 // don't let sound skip if going slow
7311 if (r_refdef.scene.extraupdate)
7314 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7316 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7317 if (r_timereport_active)
7318 R_TimeReport("worldsky");
7321 if (R_DrawBrushModelsSky() && r_timereport_active)
7322 R_TimeReport("bmodelsky");
7324 if (skyrendermasked && skyrenderlater)
7326 // we have to force off the water clipping plane while rendering sky
7327 R_SetupView(false, fbo, depthtexture, colortexture);
7329 R_SetupView(true, fbo, depthtexture, colortexture);
7330 if (r_timereport_active)
7331 R_TimeReport("sky");
7335 R_Shadow_PrepareModelShadows();
7336 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7337 if (r_timereport_active)
7338 R_TimeReport("preparelights");
7340 // render all the shadowmaps that will be used for this view
7341 shadowmapping = R_Shadow_ShadowMappingEnabled();
7342 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7344 R_Shadow_DrawShadowMaps();
7345 if (r_timereport_active)
7346 R_TimeReport("shadowmaps");
7349 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7350 if (r_shadow_usingdeferredprepass)
7351 R_Shadow_DrawPrepass();
7353 // now we begin the forward pass of the view render
7354 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7356 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7357 if (r_timereport_active)
7358 R_TimeReport("worlddepth");
7360 if (r_depthfirst.integer >= 2)
7362 R_DrawModelsDepth();
7363 if (r_timereport_active)
7364 R_TimeReport("modeldepth");
7367 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7369 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7370 if (r_timereport_active)
7371 R_TimeReport("world");
7374 // don't let sound skip if going slow
7375 if (r_refdef.scene.extraupdate)
7379 if (r_timereport_active)
7380 R_TimeReport("models");
7382 // don't let sound skip if going slow
7383 if (r_refdef.scene.extraupdate)
7386 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7388 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7389 R_Shadow_DrawModelShadows();
7390 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7391 // don't let sound skip if going slow
7392 if (r_refdef.scene.extraupdate)
7396 if (!r_shadow_usingdeferredprepass)
7398 R_Shadow_DrawLights();
7399 if (r_timereport_active)
7400 R_TimeReport("rtlights");
7403 // don't let sound skip if going slow
7404 if (r_refdef.scene.extraupdate)
7407 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7409 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7410 R_Shadow_DrawModelShadows();
7411 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7412 // don't let sound skip if going slow
7413 if (r_refdef.scene.extraupdate)
7417 if (cl.csqc_vidvars.drawworld)
7419 if (cl_decals_newsystem.integer)
7421 R_DrawModelDecals();
7422 if (r_timereport_active)
7423 R_TimeReport("modeldecals");
7428 if (r_timereport_active)
7429 R_TimeReport("decals");
7433 if (r_timereport_active)
7434 R_TimeReport("particles");
7437 if (r_timereport_active)
7438 R_TimeReport("explosions");
7441 if (r_refdef.view.showdebug)
7443 if (cl_locs_show.integer)
7446 if (r_timereport_active)
7447 R_TimeReport("showlocs");
7450 if (r_drawportals.integer)
7453 if (r_timereport_active)
7454 R_TimeReport("portals");
7457 if (r_showbboxes_client.value > 0)
7459 R_DrawEntityBBoxes(CLVM_prog);
7460 if (r_timereport_active)
7461 R_TimeReport("clbboxes");
7463 if (r_showbboxes.value > 0)
7465 R_DrawEntityBBoxes(SVVM_prog);
7466 if (r_timereport_active)
7467 R_TimeReport("svbboxes");
7471 if (r_transparent.integer)
7473 R_MeshQueue_RenderTransparent();
7474 if (r_timereport_active)
7475 R_TimeReport("drawtrans");
7478 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))
7480 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7481 if (r_timereport_active)
7482 R_TimeReport("worlddebug");
7483 R_DrawModelsDebug();
7484 if (r_timereport_active)
7485 R_TimeReport("modeldebug");
7488 if (cl.csqc_vidvars.drawworld)
7490 R_Shadow_DrawCoronas();
7491 if (r_timereport_active)
7492 R_TimeReport("coronas");
7497 GL_DepthTest(false);
7498 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7499 GL_Color(1, 1, 1, 1);
7500 qglBegin(GL_POLYGON);
7501 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7502 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7503 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7504 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7506 qglBegin(GL_POLYGON);
7507 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]);
7508 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]);
7509 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]);
7510 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]);
7512 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7516 // don't let sound skip if going slow
7517 if (r_refdef.scene.extraupdate)
7521 static const unsigned short bboxelements[36] =
7531 #define BBOXEDGES 13
7532 static const float bboxedges[BBOXEDGES][6] =
7535 { 0, 0, 0, 1, 1, 1 },
7537 { 0, 0, 0, 0, 1, 0 },
7538 { 0, 0, 0, 1, 0, 0 },
7539 { 0, 1, 0, 1, 1, 0 },
7540 { 1, 0, 0, 1, 1, 0 },
7542 { 0, 0, 1, 0, 1, 1 },
7543 { 0, 0, 1, 1, 0, 1 },
7544 { 0, 1, 1, 1, 1, 1 },
7545 { 1, 0, 1, 1, 1, 1 },
7547 { 0, 0, 0, 0, 0, 1 },
7548 { 1, 0, 0, 1, 0, 1 },
7549 { 0, 1, 0, 0, 1, 1 },
7550 { 1, 1, 0, 1, 1, 1 },
7553 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7555 int numvertices = BBOXEDGES * 8;
7556 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7557 int numtriangles = BBOXEDGES * 12;
7558 unsigned short elements[BBOXEDGES * 36];
7560 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7562 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7564 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7565 GL_DepthMask(false);
7566 GL_DepthRange(0, 1);
7567 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7569 for (edge = 0; edge < BBOXEDGES; edge++)
7571 for (i = 0; i < 3; i++)
7573 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7574 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7576 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7577 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7578 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7579 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7580 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7581 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7582 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7583 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7584 for (i = 0; i < 36; i++)
7585 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7587 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7588 if (r_refdef.fogenabled)
7590 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7592 f1 = RSurf_FogVertex(v);
7594 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7595 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7596 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7599 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7600 R_Mesh_ResetTextureState();
7601 R_SetupShader_Generic_NoTexture(false, false);
7602 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7605 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7607 // hacky overloading of the parameters
7608 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7611 prvm_edict_t *edict;
7613 GL_CullFace(GL_NONE);
7614 R_SetupShader_Generic_NoTexture(false, false);
7616 for (i = 0;i < numsurfaces;i++)
7618 edict = PRVM_EDICT_NUM(surfacelist[i]);
7619 switch ((int)PRVM_serveredictfloat(edict, solid))
7621 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7622 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7623 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7624 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7625 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7626 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7627 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7629 if (prog == CLVM_prog)
7630 color[3] *= r_showbboxes_client.value;
7632 color[3] *= r_showbboxes.value;
7633 color[3] = bound(0, color[3], 1);
7634 GL_DepthTest(!r_showdisabledepthtest.integer);
7635 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7639 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7642 prvm_edict_t *edict;
7648 for (i = 0; i < prog->num_edicts; i++)
7650 edict = PRVM_EDICT_NUM(i);
7651 if (edict->priv.server->free)
7653 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7654 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7656 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7658 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7659 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7663 static const int nomodelelement3i[24] =
7675 static const unsigned short nomodelelement3s[24] =
7687 static const float nomodelvertex3f[6*3] =
7697 static const float nomodelcolor4f[6*4] =
7699 0.0f, 0.0f, 0.5f, 1.0f,
7700 0.0f, 0.0f, 0.5f, 1.0f,
7701 0.0f, 0.5f, 0.0f, 1.0f,
7702 0.0f, 0.5f, 0.0f, 1.0f,
7703 0.5f, 0.0f, 0.0f, 1.0f,
7704 0.5f, 0.0f, 0.0f, 1.0f
7707 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7713 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);
7715 // this is only called once per entity so numsurfaces is always 1, and
7716 // surfacelist is always {0}, so this code does not handle batches
7718 if (rsurface.ent_flags & RENDER_ADDITIVE)
7720 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7721 GL_DepthMask(false);
7723 else if (ent->alpha < 1)
7725 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7726 GL_DepthMask(false);
7730 GL_BlendFunc(GL_ONE, GL_ZERO);
7733 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7734 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7735 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7736 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7737 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7738 for (i = 0, c = color4f;i < 6;i++, c += 4)
7740 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7741 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7742 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7745 if (r_refdef.fogenabled)
7747 for (i = 0, c = color4f;i < 6;i++, c += 4)
7749 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7751 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7752 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7753 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7756 // R_Mesh_ResetTextureState();
7757 R_SetupShader_Generic_NoTexture(false, false);
7758 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7759 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7762 void R_DrawNoModel(entity_render_t *ent)
7765 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7766 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7767 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7769 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7772 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7774 vec3_t right1, right2, diff, normal;
7776 VectorSubtract (org2, org1, normal);
7778 // calculate 'right' vector for start
7779 VectorSubtract (r_refdef.view.origin, org1, diff);
7780 CrossProduct (normal, diff, right1);
7781 VectorNormalize (right1);
7783 // calculate 'right' vector for end
7784 VectorSubtract (r_refdef.view.origin, org2, diff);
7785 CrossProduct (normal, diff, right2);
7786 VectorNormalize (right2);
7788 vert[ 0] = org1[0] + width * right1[0];
7789 vert[ 1] = org1[1] + width * right1[1];
7790 vert[ 2] = org1[2] + width * right1[2];
7791 vert[ 3] = org1[0] - width * right1[0];
7792 vert[ 4] = org1[1] - width * right1[1];
7793 vert[ 5] = org1[2] - width * right1[2];
7794 vert[ 6] = org2[0] - width * right2[0];
7795 vert[ 7] = org2[1] - width * right2[1];
7796 vert[ 8] = org2[2] - width * right2[2];
7797 vert[ 9] = org2[0] + width * right2[0];
7798 vert[10] = org2[1] + width * right2[1];
7799 vert[11] = org2[2] + width * right2[2];
7802 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)
7804 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7805 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7806 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7807 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7808 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7809 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7810 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7811 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7812 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7813 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7814 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7815 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7818 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7823 VectorSet(v, x, y, z);
7824 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7825 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7827 if (i == mesh->numvertices)
7829 if (mesh->numvertices < mesh->maxvertices)
7831 VectorCopy(v, vertex3f);
7832 mesh->numvertices++;
7834 return mesh->numvertices;
7840 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7844 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7845 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7846 e = mesh->element3i + mesh->numtriangles * 3;
7847 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7849 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7850 if (mesh->numtriangles < mesh->maxtriangles)
7855 mesh->numtriangles++;
7857 element[1] = element[2];
7861 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7865 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7866 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7867 e = mesh->element3i + mesh->numtriangles * 3;
7868 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7870 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7871 if (mesh->numtriangles < mesh->maxtriangles)
7876 mesh->numtriangles++;
7878 element[1] = element[2];
7882 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7883 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7885 int planenum, planenum2;
7888 mplane_t *plane, *plane2;
7890 double temppoints[2][256*3];
7891 // figure out how large a bounding box we need to properly compute this brush
7893 for (w = 0;w < numplanes;w++)
7894 maxdist = max(maxdist, fabs(planes[w].dist));
7895 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7896 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7897 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7901 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7902 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7904 if (planenum2 == planenum)
7906 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);
7909 if (tempnumpoints < 3)
7911 // generate elements forming a triangle fan for this polygon
7912 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7916 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)
7918 texturelayer_t *layer;
7919 layer = t->currentlayers + t->currentnumlayers++;
7921 layer->depthmask = depthmask;
7922 layer->blendfunc1 = blendfunc1;
7923 layer->blendfunc2 = blendfunc2;
7924 layer->texture = texture;
7925 layer->texmatrix = *matrix;
7926 layer->color[0] = r;
7927 layer->color[1] = g;
7928 layer->color[2] = b;
7929 layer->color[3] = a;
7932 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7934 if(parms[0] == 0 && parms[1] == 0)
7936 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7937 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7942 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7945 index = parms[2] + rsurface.shadertime * parms[3];
7946 index -= floor(index);
7947 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7950 case Q3WAVEFUNC_NONE:
7951 case Q3WAVEFUNC_NOISE:
7952 case Q3WAVEFUNC_COUNT:
7955 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7956 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7957 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7958 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7959 case Q3WAVEFUNC_TRIANGLE:
7961 f = index - floor(index);
7974 f = parms[0] + parms[1] * f;
7975 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7976 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7980 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7987 matrix4x4_t matrix, temp;
7988 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7989 // it's better to have one huge fixup every 9 hours than gradual
7990 // degradation over time which looks consistently bad after many hours.
7992 // tcmod scroll in particular suffers from this degradation which can't be
7993 // effectively worked around even with floor() tricks because we don't
7994 // know if tcmod scroll is the last tcmod being applied, and for clampmap
7995 // a workaround involving floor() would be incorrect anyway...
7996 shadertime = rsurface.shadertime;
7997 if (shadertime >= 32768.0f)
7998 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7999 switch(tcmod->tcmod)
8003 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8004 matrix = r_waterscrollmatrix;
8006 matrix = identitymatrix;
8008 case Q3TCMOD_ENTITYTRANSLATE:
8009 // this is used in Q3 to allow the gamecode to control texcoord
8010 // scrolling on the entity, which is not supported in darkplaces yet.
8011 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8013 case Q3TCMOD_ROTATE:
8014 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8015 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8016 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8019 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8021 case Q3TCMOD_SCROLL:
8022 // this particular tcmod is a "bug for bug" compatible one with regards to
8023 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8024 // specifically did the wrapping and so we must mimic that...
8025 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8026 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8027 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8029 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8030 w = (int) tcmod->parms[0];
8031 h = (int) tcmod->parms[1];
8032 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8034 idx = (int) floor(f * w * h);
8035 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8037 case Q3TCMOD_STRETCH:
8038 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8039 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8041 case Q3TCMOD_TRANSFORM:
8042 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8043 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8044 VectorSet(tcmat + 6, 0 , 0 , 1);
8045 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8046 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8048 case Q3TCMOD_TURBULENT:
8049 // this is handled in the RSurf_PrepareVertices function
8050 matrix = identitymatrix;
8054 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8057 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8059 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8060 char name[MAX_QPATH];
8061 skinframe_t *skinframe;
8062 unsigned char pixels[296*194];
8063 strlcpy(cache->name, skinname, sizeof(cache->name));
8064 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8065 if (developer_loading.integer)
8066 Con_Printf("loading %s\n", name);
8067 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8068 if (!skinframe || !skinframe->base)
8071 fs_offset_t filesize;
8073 f = FS_LoadFile(name, tempmempool, true, &filesize);
8076 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8077 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8081 cache->skinframe = skinframe;
8084 texture_t *R_GetCurrentTexture(texture_t *t)
8087 const entity_render_t *ent = rsurface.entity;
8088 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8089 q3shaderinfo_layer_tcmod_t *tcmod;
8090 float specularscale = 0.0f;
8092 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8093 return t->currentframe;
8094 t->update_lastrenderframe = r_textureframe;
8095 t->update_lastrenderentity = (void *)ent;
8097 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8098 t->camera_entity = ent->entitynumber;
8100 t->camera_entity = 0;
8102 // switch to an alternate material if this is a q1bsp animated material
8104 texture_t *texture = t;
8105 int s = rsurface.ent_skinnum;
8106 if ((unsigned int)s >= (unsigned int)model->numskins)
8108 if (model->skinscenes)
8110 if (model->skinscenes[s].framecount > 1)
8111 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8113 s = model->skinscenes[s].firstframe;
8116 t = t + s * model->num_surfaces;
8119 // use an alternate animation if the entity's frame is not 0,
8120 // and only if the texture has an alternate animation
8121 if (t->animated == 2) // q2bsp
8122 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8123 else if (rsurface.ent_alttextures && t->anim_total[1])
8124 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8126 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8128 texture->currentframe = t;
8131 // update currentskinframe to be a qw skin or animation frame
8132 if (rsurface.ent_qwskin >= 0)
8134 i = rsurface.ent_qwskin;
8135 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8137 r_qwskincache_size = cl.maxclients;
8139 Mem_Free(r_qwskincache);
8140 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8142 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8143 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8144 t->currentskinframe = r_qwskincache[i].skinframe;
8145 if (t->materialshaderpass && t->currentskinframe == NULL)
8146 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8148 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8149 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8150 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8151 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8153 t->currentmaterialflags = t->basematerialflags;
8154 t->currentalpha = rsurface.entity->alpha * t->basealpha;
8155 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8156 t->currentalpha *= r_wateralpha.value;
8157 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8158 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8159 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8160 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8162 // decide on which type of lighting to use for this surface
8163 if (rsurface.entity->render_modellight_forced)
8164 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8165 if (rsurface.entity->render_rtlight_disabled)
8166 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8167 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8169 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
8170 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
8171 for (q = 0; q < 3; q++)
8173 t->render_glowmod[q] = rsurface.entity->glowmod[q];
8174 t->render_modellight_lightdir[q] = q == 2;
8175 t->render_modellight_ambient[q] = 1;
8176 t->render_modellight_diffuse[q] = 0;
8177 t->render_modellight_specular[q] = 0;
8178 t->render_lightmap_ambient[q] = 0;
8179 t->render_lightmap_diffuse[q] = 0;
8180 t->render_lightmap_specular[q] = 0;
8181 t->render_rtlight_diffuse[q] = 0;
8182 t->render_rtlight_specular[q] = 0;
8185 else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8187 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8188 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8189 for (q = 0; q < 3; q++)
8191 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8192 t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8193 t->render_modellight_lightdir[q] = q == 2;
8194 t->render_modellight_diffuse[q] = 0;
8195 t->render_modellight_specular[q] = 0;
8196 t->render_lightmap_ambient[q] = 0;
8197 t->render_lightmap_diffuse[q] = 0;
8198 t->render_lightmap_specular[q] = 0;
8199 t->render_rtlight_diffuse[q] = 0;
8200 t->render_rtlight_specular[q] = 0;
8203 else if (FAKELIGHT_ENABLED)
8205 // no modellight if using fakelight for the map
8206 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8207 for (q = 0; q < 3; q++)
8209 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8210 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8211 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8212 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8213 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8214 t->render_lightmap_ambient[q] = 0;
8215 t->render_lightmap_diffuse[q] = 0;
8216 t->render_lightmap_specular[q] = 0;
8217 t->render_rtlight_diffuse[q] = 0;
8218 t->render_rtlight_specular[q] = 0;
8221 else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8223 // ambient + single direction light (modellight)
8224 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8225 for (q = 0; q < 3; q++)
8227 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8228 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8229 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8230 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8231 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8232 t->render_lightmap_ambient[q] = 0;
8233 t->render_lightmap_diffuse[q] = 0;
8234 t->render_lightmap_specular[q] = 0;
8235 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8236 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8241 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8242 for (q = 0; q < 3; q++)
8244 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8245 t->render_modellight_lightdir[q] = q == 2;
8246 t->render_modellight_ambient[q] = 0;
8247 t->render_modellight_diffuse[q] = 0;
8248 t->render_modellight_specular[q] = 0;
8249 t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8250 t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8251 t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8252 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8253 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8257 if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8259 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8260 // attribute, we punt it to the lightmap path and hope for the best,
8261 // but lighting doesn't work.
8263 // FIXME: this is fine for effects but CSQC polygons should be subject
8265 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8266 for (q = 0; q < 3; q++)
8268 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8269 t->render_modellight_lightdir[q] = q == 2;
8270 t->render_modellight_ambient[q] = 0;
8271 t->render_modellight_diffuse[q] = 0;
8272 t->render_modellight_specular[q] = 0;
8273 t->render_lightmap_ambient[q] = 0;
8274 t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8275 t->render_lightmap_specular[q] = 0;
8276 t->render_rtlight_diffuse[q] = 0;
8277 t->render_rtlight_specular[q] = 0;
8281 for (q = 0; q < 3; q++)
8283 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8284 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8287 if (rsurface.ent_flags & RENDER_ADDITIVE)
8288 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8289 else if (t->currentalpha < 1)
8290 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8291 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8292 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8293 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8294 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8295 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8296 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8297 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8298 if (t->backgroundshaderpass)
8299 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8300 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8302 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8303 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8306 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8307 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8309 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8310 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8312 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8313 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8315 // there is no tcmod
8316 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8318 t->currenttexmatrix = r_waterscrollmatrix;
8319 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8321 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8323 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8324 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8327 if (t->materialshaderpass)
8328 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8329 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8331 t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8332 if (t->currentskinframe->qpixels)
8333 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8334 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8335 if (!t->basetexture)
8336 t->basetexture = r_texture_notexture;
8337 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8338 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8339 t->nmaptexture = t->currentskinframe->nmap;
8340 if (!t->nmaptexture)
8341 t->nmaptexture = r_texture_blanknormalmap;
8342 t->glosstexture = r_texture_black;
8343 t->glowtexture = t->currentskinframe->glow;
8344 t->fogtexture = t->currentskinframe->fog;
8345 t->reflectmasktexture = t->currentskinframe->reflect;
8346 if (t->backgroundshaderpass)
8348 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8349 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8350 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8351 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8352 t->backgroundglosstexture = r_texture_black;
8353 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8354 if (!t->backgroundnmaptexture)
8355 t->backgroundnmaptexture = r_texture_blanknormalmap;
8356 // make sure that if glow is going to be used, both textures are not NULL
8357 if (!t->backgroundglowtexture && t->glowtexture)
8358 t->backgroundglowtexture = r_texture_black;
8359 if (!t->glowtexture && t->backgroundglowtexture)
8360 t->glowtexture = r_texture_black;
8364 t->backgroundbasetexture = r_texture_white;
8365 t->backgroundnmaptexture = r_texture_blanknormalmap;
8366 t->backgroundglosstexture = r_texture_black;
8367 t->backgroundglowtexture = NULL;
8369 t->specularpower = r_shadow_glossexponent.value;
8370 // TODO: store reference values for these in the texture?
8371 if (r_shadow_gloss.integer > 0)
8373 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8375 if (r_shadow_glossintensity.value > 0)
8377 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8378 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8379 specularscale = r_shadow_glossintensity.value;
8382 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8384 t->glosstexture = r_texture_white;
8385 t->backgroundglosstexture = r_texture_white;
8386 specularscale = r_shadow_gloss2intensity.value;
8387 t->specularpower = r_shadow_gloss2exponent.value;
8390 specularscale *= t->specularscalemod;
8391 t->specularpower *= t->specularpowermod;
8393 // lightmaps mode looks bad with dlights using actual texturing, so turn
8394 // off the colormap and glossmap, but leave the normalmap on as it still
8395 // accurately represents the shading involved
8396 if (gl_lightmaps.integer)
8398 t->basetexture = r_texture_grey128;
8399 t->pantstexture = r_texture_black;
8400 t->shirttexture = r_texture_black;
8401 if (gl_lightmaps.integer < 2)
8402 t->nmaptexture = r_texture_blanknormalmap;
8403 t->glosstexture = r_texture_black;
8404 t->glowtexture = NULL;
8405 t->fogtexture = NULL;
8406 t->reflectmasktexture = NULL;
8407 t->backgroundbasetexture = NULL;
8408 if (gl_lightmaps.integer < 2)
8409 t->backgroundnmaptexture = r_texture_blanknormalmap;
8410 t->backgroundglosstexture = r_texture_black;
8411 t->backgroundglowtexture = NULL;
8413 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8416 if (specularscale != 1.0f)
8418 for (q = 0; q < 3; q++)
8420 t->render_modellight_specular[q] *= specularscale;
8421 t->render_lightmap_specular[q] *= specularscale;
8422 t->render_rtlight_specular[q] *= specularscale;
8426 t->currentnumlayers = 0;
8427 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8429 int blendfunc1, blendfunc2;
8431 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8433 blendfunc1 = GL_SRC_ALPHA;
8434 blendfunc2 = GL_ONE;
8436 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8438 blendfunc1 = GL_SRC_ALPHA;
8439 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8441 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8443 blendfunc1 = t->customblendfunc[0];
8444 blendfunc2 = t->customblendfunc[1];
8448 blendfunc1 = GL_ONE;
8449 blendfunc2 = GL_ZERO;
8451 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8452 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8454 // basic lit geometry
8455 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8456 // add pants/shirt if needed
8457 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8458 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8459 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8460 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8464 // basic lit geometry
8465 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8466 // add pants/shirt if needed
8467 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8468 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8469 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8470 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8471 // now add ambient passes if needed
8472 if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8474 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8475 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8476 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8477 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8478 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8481 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8482 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8483 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8485 // if this is opaque use alpha blend which will darken the earlier
8488 // if this is an alpha blended material, all the earlier passes
8489 // were darkened by fog already, so we only need to add the fog
8490 // color ontop through the fog mask texture
8492 // if this is an additive blended material, all the earlier passes
8493 // were darkened by fog already, and we should not add fog color
8494 // (because the background was not darkened, there is no fog color
8495 // that was lost behind it).
8496 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
8503 rsurfacestate_t rsurface;
8505 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8507 dp_model_t *model = ent->model;
8508 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8510 rsurface.entity = (entity_render_t *)ent;
8511 rsurface.skeleton = ent->skeleton;
8512 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8513 rsurface.ent_skinnum = ent->skinnum;
8514 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;
8515 rsurface.ent_flags = ent->flags;
8516 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8517 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8518 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8519 rsurface.matrix = ent->matrix;
8520 rsurface.inversematrix = ent->inversematrix;
8521 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8522 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8523 R_EntityMatrix(&rsurface.matrix);
8524 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8525 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8526 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8527 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8528 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8529 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8530 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8531 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8532 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8533 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8534 if (ent->model->brush.submodel && !prepass)
8536 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8537 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8539 // if the animcache code decided it should use the shader path, skip the deform step
8540 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8541 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8542 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8543 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8544 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8545 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8547 if (ent->animcache_vertex3f)
8549 r_refdef.stats[r_stat_batch_entitycache_count]++;
8550 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8551 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8552 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8553 rsurface.modelvertex3f = ent->animcache_vertex3f;
8554 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8555 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8556 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8557 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8558 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8559 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8560 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8561 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8562 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8563 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8564 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8565 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8566 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8567 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8569 else if (wanttangents)
8571 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8572 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8573 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8574 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8575 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8576 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8577 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8578 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8579 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8580 rsurface.modelvertexmesh = NULL;
8581 rsurface.modelvertexmesh_vertexbuffer = NULL;
8582 rsurface.modelvertexmesh_bufferoffset = 0;
8583 rsurface.modelvertex3f_vertexbuffer = NULL;
8584 rsurface.modelvertex3f_bufferoffset = 0;
8585 rsurface.modelvertex3f_vertexbuffer = 0;
8586 rsurface.modelvertex3f_bufferoffset = 0;
8587 rsurface.modelsvector3f_vertexbuffer = 0;
8588 rsurface.modelsvector3f_bufferoffset = 0;
8589 rsurface.modeltvector3f_vertexbuffer = 0;
8590 rsurface.modeltvector3f_bufferoffset = 0;
8591 rsurface.modelnormal3f_vertexbuffer = 0;
8592 rsurface.modelnormal3f_bufferoffset = 0;
8594 else if (wantnormals)
8596 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8597 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8598 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8599 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8600 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8601 rsurface.modelsvector3f = NULL;
8602 rsurface.modeltvector3f = NULL;
8603 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8604 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8605 rsurface.modelvertexmesh = NULL;
8606 rsurface.modelvertexmesh_vertexbuffer = NULL;
8607 rsurface.modelvertexmesh_bufferoffset = 0;
8608 rsurface.modelvertex3f_vertexbuffer = NULL;
8609 rsurface.modelvertex3f_bufferoffset = 0;
8610 rsurface.modelvertex3f_vertexbuffer = 0;
8611 rsurface.modelvertex3f_bufferoffset = 0;
8612 rsurface.modelsvector3f_vertexbuffer = 0;
8613 rsurface.modelsvector3f_bufferoffset = 0;
8614 rsurface.modeltvector3f_vertexbuffer = 0;
8615 rsurface.modeltvector3f_bufferoffset = 0;
8616 rsurface.modelnormal3f_vertexbuffer = 0;
8617 rsurface.modelnormal3f_bufferoffset = 0;
8621 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8622 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8623 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8624 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8625 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8626 rsurface.modelsvector3f = NULL;
8627 rsurface.modeltvector3f = NULL;
8628 rsurface.modelnormal3f = NULL;
8629 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8630 rsurface.modelvertexmesh = NULL;
8631 rsurface.modelvertexmesh_vertexbuffer = NULL;
8632 rsurface.modelvertexmesh_bufferoffset = 0;
8633 rsurface.modelvertex3f_vertexbuffer = NULL;
8634 rsurface.modelvertex3f_bufferoffset = 0;
8635 rsurface.modelvertex3f_vertexbuffer = 0;
8636 rsurface.modelvertex3f_bufferoffset = 0;
8637 rsurface.modelsvector3f_vertexbuffer = 0;
8638 rsurface.modelsvector3f_bufferoffset = 0;
8639 rsurface.modeltvector3f_vertexbuffer = 0;
8640 rsurface.modeltvector3f_bufferoffset = 0;
8641 rsurface.modelnormal3f_vertexbuffer = 0;
8642 rsurface.modelnormal3f_bufferoffset = 0;
8644 rsurface.modelgeneratedvertex = true;
8648 if (rsurface.entityskeletaltransform3x4)
8650 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8651 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8652 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8653 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8657 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8658 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8659 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8660 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8662 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8663 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8664 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8665 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8666 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8667 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8668 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8669 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8670 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8671 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8672 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8673 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8674 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8675 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8676 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8677 rsurface.modelgeneratedvertex = false;
8679 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8680 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8681 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8682 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8683 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8684 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8685 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8686 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8687 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8688 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8689 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8690 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8691 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8692 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8693 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8694 rsurface.modelelement3i = model->surfmesh.data_element3i;
8695 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8696 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8697 rsurface.modelelement3s = model->surfmesh.data_element3s;
8698 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8699 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8700 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8701 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8702 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8703 rsurface.modelsurfaces = model->data_surfaces;
8704 rsurface.batchgeneratedvertex = false;
8705 rsurface.batchfirstvertex = 0;
8706 rsurface.batchnumvertices = 0;
8707 rsurface.batchfirsttriangle = 0;
8708 rsurface.batchnumtriangles = 0;
8709 rsurface.batchvertex3f = NULL;
8710 rsurface.batchvertex3f_vertexbuffer = NULL;
8711 rsurface.batchvertex3f_bufferoffset = 0;
8712 rsurface.batchsvector3f = NULL;
8713 rsurface.batchsvector3f_vertexbuffer = NULL;
8714 rsurface.batchsvector3f_bufferoffset = 0;
8715 rsurface.batchtvector3f = NULL;
8716 rsurface.batchtvector3f_vertexbuffer = NULL;
8717 rsurface.batchtvector3f_bufferoffset = 0;
8718 rsurface.batchnormal3f = NULL;
8719 rsurface.batchnormal3f_vertexbuffer = NULL;
8720 rsurface.batchnormal3f_bufferoffset = 0;
8721 rsurface.batchlightmapcolor4f = NULL;
8722 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8723 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8724 rsurface.batchtexcoordtexture2f = NULL;
8725 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8726 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8727 rsurface.batchtexcoordlightmap2f = NULL;
8728 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8729 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8730 rsurface.batchskeletalindex4ub = NULL;
8731 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8732 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8733 rsurface.batchskeletalweight4ub = NULL;
8734 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8735 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8736 rsurface.batchvertexmesh = NULL;
8737 rsurface.batchvertexmesh_vertexbuffer = NULL;
8738 rsurface.batchvertexmesh_bufferoffset = 0;
8739 rsurface.batchelement3i = NULL;
8740 rsurface.batchelement3i_indexbuffer = NULL;
8741 rsurface.batchelement3i_bufferoffset = 0;
8742 rsurface.batchelement3s = NULL;
8743 rsurface.batchelement3s_indexbuffer = NULL;
8744 rsurface.batchelement3s_bufferoffset = 0;
8745 rsurface.passcolor4f = NULL;
8746 rsurface.passcolor4f_vertexbuffer = NULL;
8747 rsurface.passcolor4f_bufferoffset = 0;
8748 rsurface.forcecurrenttextureupdate = false;
8751 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)
8753 rsurface.entity = r_refdef.scene.worldentity;
8754 rsurface.skeleton = NULL;
8755 rsurface.ent_skinnum = 0;
8756 rsurface.ent_qwskin = -1;
8757 rsurface.ent_flags = entflags;
8758 rsurface.shadertime = r_refdef.scene.time - shadertime;
8759 rsurface.modelnumvertices = numvertices;
8760 rsurface.modelnumtriangles = numtriangles;
8761 rsurface.matrix = *matrix;
8762 rsurface.inversematrix = *inversematrix;
8763 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8764 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8765 R_EntityMatrix(&rsurface.matrix);
8766 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8767 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8768 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8769 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8770 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8771 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8772 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8773 rsurface.frameblend[0].lerp = 1;
8774 rsurface.ent_alttextures = false;
8775 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8776 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8777 rsurface.entityskeletaltransform3x4 = NULL;
8778 rsurface.entityskeletaltransform3x4buffer = NULL;
8779 rsurface.entityskeletaltransform3x4offset = 0;
8780 rsurface.entityskeletaltransform3x4size = 0;
8781 rsurface.entityskeletalnumtransforms = 0;
8782 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8783 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8784 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8785 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8788 rsurface.modelvertex3f = (float *)vertex3f;
8789 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8790 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8791 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8793 else if (wantnormals)
8795 rsurface.modelvertex3f = (float *)vertex3f;
8796 rsurface.modelsvector3f = NULL;
8797 rsurface.modeltvector3f = NULL;
8798 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8802 rsurface.modelvertex3f = (float *)vertex3f;
8803 rsurface.modelsvector3f = NULL;
8804 rsurface.modeltvector3f = NULL;
8805 rsurface.modelnormal3f = NULL;
8807 rsurface.modelvertexmesh = NULL;
8808 rsurface.modelvertexmesh_vertexbuffer = NULL;
8809 rsurface.modelvertexmesh_bufferoffset = 0;
8810 rsurface.modelvertex3f_vertexbuffer = 0;
8811 rsurface.modelvertex3f_bufferoffset = 0;
8812 rsurface.modelsvector3f_vertexbuffer = 0;
8813 rsurface.modelsvector3f_bufferoffset = 0;
8814 rsurface.modeltvector3f_vertexbuffer = 0;
8815 rsurface.modeltvector3f_bufferoffset = 0;
8816 rsurface.modelnormal3f_vertexbuffer = 0;
8817 rsurface.modelnormal3f_bufferoffset = 0;
8818 rsurface.modelgeneratedvertex = true;
8819 rsurface.modellightmapcolor4f = (float *)color4f;
8820 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8821 rsurface.modellightmapcolor4f_bufferoffset = 0;
8822 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8823 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8824 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8825 rsurface.modeltexcoordlightmap2f = NULL;
8826 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8827 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8828 rsurface.modelskeletalindex4ub = NULL;
8829 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8830 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8831 rsurface.modelskeletalweight4ub = NULL;
8832 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8833 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8834 rsurface.modelelement3i = (int *)element3i;
8835 rsurface.modelelement3i_indexbuffer = NULL;
8836 rsurface.modelelement3i_bufferoffset = 0;
8837 rsurface.modelelement3s = (unsigned short *)element3s;
8838 rsurface.modelelement3s_indexbuffer = NULL;
8839 rsurface.modelelement3s_bufferoffset = 0;
8840 rsurface.modellightmapoffsets = NULL;
8841 rsurface.modelsurfaces = NULL;
8842 rsurface.batchgeneratedvertex = false;
8843 rsurface.batchfirstvertex = 0;
8844 rsurface.batchnumvertices = 0;
8845 rsurface.batchfirsttriangle = 0;
8846 rsurface.batchnumtriangles = 0;
8847 rsurface.batchvertex3f = NULL;
8848 rsurface.batchvertex3f_vertexbuffer = NULL;
8849 rsurface.batchvertex3f_bufferoffset = 0;
8850 rsurface.batchsvector3f = NULL;
8851 rsurface.batchsvector3f_vertexbuffer = NULL;
8852 rsurface.batchsvector3f_bufferoffset = 0;
8853 rsurface.batchtvector3f = NULL;
8854 rsurface.batchtvector3f_vertexbuffer = NULL;
8855 rsurface.batchtvector3f_bufferoffset = 0;
8856 rsurface.batchnormal3f = NULL;
8857 rsurface.batchnormal3f_vertexbuffer = NULL;
8858 rsurface.batchnormal3f_bufferoffset = 0;
8859 rsurface.batchlightmapcolor4f = NULL;
8860 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8861 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8862 rsurface.batchtexcoordtexture2f = NULL;
8863 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8864 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8865 rsurface.batchtexcoordlightmap2f = NULL;
8866 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8867 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8868 rsurface.batchskeletalindex4ub = NULL;
8869 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8870 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8871 rsurface.batchskeletalweight4ub = NULL;
8872 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8873 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8874 rsurface.batchvertexmesh = NULL;
8875 rsurface.batchvertexmesh_vertexbuffer = NULL;
8876 rsurface.batchvertexmesh_bufferoffset = 0;
8877 rsurface.batchelement3i = NULL;
8878 rsurface.batchelement3i_indexbuffer = NULL;
8879 rsurface.batchelement3i_bufferoffset = 0;
8880 rsurface.batchelement3s = NULL;
8881 rsurface.batchelement3s_indexbuffer = NULL;
8882 rsurface.batchelement3s_bufferoffset = 0;
8883 rsurface.passcolor4f = NULL;
8884 rsurface.passcolor4f_vertexbuffer = NULL;
8885 rsurface.passcolor4f_bufferoffset = 0;
8886 rsurface.forcecurrenttextureupdate = true;
8888 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8890 if ((wantnormals || wanttangents) && !normal3f)
8892 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8893 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8895 if (wanttangents && !svector3f)
8897 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8898 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8899 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8904 float RSurf_FogPoint(const float *v)
8906 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8907 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8908 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8909 float FogHeightFade = r_refdef.fogheightfade;
8911 unsigned int fogmasktableindex;
8912 if (r_refdef.fogplaneviewabove)
8913 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8915 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8916 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8917 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8920 float RSurf_FogVertex(const float *v)
8922 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8923 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8924 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8925 float FogHeightFade = rsurface.fogheightfade;
8927 unsigned int fogmasktableindex;
8928 if (r_refdef.fogplaneviewabove)
8929 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8931 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8932 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8933 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8936 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8939 for (i = 0;i < numelements;i++)
8940 outelement3i[i] = inelement3i[i] + adjust;
8943 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8944 extern cvar_t gl_vbo;
8945 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8953 int surfacefirsttriangle;
8954 int surfacenumtriangles;
8955 int surfacefirstvertex;
8956 int surfaceendvertex;
8957 int surfacenumvertices;
8958 int batchnumsurfaces = texturenumsurfaces;
8959 int batchnumvertices;
8960 int batchnumtriangles;
8964 qboolean dynamicvertex;
8967 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8970 q3shaderinfo_deform_t *deform;
8971 const msurface_t *surface, *firstsurface;
8972 r_vertexmesh_t *vertexmesh;
8973 if (!texturenumsurfaces)
8975 // find vertex range of this surface batch
8977 firstsurface = texturesurfacelist[0];
8978 firsttriangle = firstsurface->num_firsttriangle;
8979 batchnumvertices = 0;
8980 batchnumtriangles = 0;
8981 firstvertex = endvertex = firstsurface->num_firstvertex;
8982 for (i = 0;i < texturenumsurfaces;i++)
8984 surface = texturesurfacelist[i];
8985 if (surface != firstsurface + i)
8987 surfacefirstvertex = surface->num_firstvertex;
8988 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8989 surfacenumvertices = surface->num_vertices;
8990 surfacenumtriangles = surface->num_triangles;
8991 if (firstvertex > surfacefirstvertex)
8992 firstvertex = surfacefirstvertex;
8993 if (endvertex < surfaceendvertex)
8994 endvertex = surfaceendvertex;
8995 batchnumvertices += surfacenumvertices;
8996 batchnumtriangles += surfacenumtriangles;
8999 r_refdef.stats[r_stat_batch_batches]++;
9001 r_refdef.stats[r_stat_batch_withgaps]++;
9002 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9003 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9004 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9006 // we now know the vertex range used, and if there are any gaps in it
9007 rsurface.batchfirstvertex = firstvertex;
9008 rsurface.batchnumvertices = endvertex - firstvertex;
9009 rsurface.batchfirsttriangle = firsttriangle;
9010 rsurface.batchnumtriangles = batchnumtriangles;
9012 // this variable holds flags for which properties have been updated that
9013 // may require regenerating vertexmesh array...
9016 // check if any dynamic vertex processing must occur
9017 dynamicvertex = false;
9019 // a cvar to force the dynamic vertex path to be taken, for debugging
9020 if (r_batch_debugdynamicvertexpath.integer)
9024 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9025 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9026 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9027 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9029 dynamicvertex = true;
9032 // if there is a chance of animated vertex colors, it's a dynamic batch
9033 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9037 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9038 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9039 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9040 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9042 dynamicvertex = true;
9043 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9046 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9048 switch (deform->deform)
9051 case Q3DEFORM_PROJECTIONSHADOW:
9052 case Q3DEFORM_TEXT0:
9053 case Q3DEFORM_TEXT1:
9054 case Q3DEFORM_TEXT2:
9055 case Q3DEFORM_TEXT3:
9056 case Q3DEFORM_TEXT4:
9057 case Q3DEFORM_TEXT5:
9058 case Q3DEFORM_TEXT6:
9059 case Q3DEFORM_TEXT7:
9062 case Q3DEFORM_AUTOSPRITE:
9065 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9066 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9067 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9068 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9070 dynamicvertex = true;
9071 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9072 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9074 case Q3DEFORM_AUTOSPRITE2:
9077 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9078 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9079 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9080 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9082 dynamicvertex = true;
9083 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9084 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9086 case Q3DEFORM_NORMAL:
9089 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9090 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9091 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9092 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9094 dynamicvertex = true;
9095 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9096 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9099 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9100 break; // if wavefunc is a nop, ignore this transform
9103 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9104 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9105 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9106 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9108 dynamicvertex = true;
9109 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9110 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9112 case Q3DEFORM_BULGE:
9115 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9116 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9117 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9118 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9120 dynamicvertex = true;
9121 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9122 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9125 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9126 break; // if wavefunc is a nop, ignore this transform
9129 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9130 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9131 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9132 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9134 dynamicvertex = true;
9135 batchneed |= BATCHNEED_ARRAY_VERTEX;
9136 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9140 if (rsurface.texture->materialshaderpass)
9142 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9145 case Q3TCGEN_TEXTURE:
9147 case Q3TCGEN_LIGHTMAP:
9150 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9151 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9152 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9153 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9155 dynamicvertex = true;
9156 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9157 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9159 case Q3TCGEN_VECTOR:
9162 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9163 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9164 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9165 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9167 dynamicvertex = true;
9168 batchneed |= BATCHNEED_ARRAY_VERTEX;
9169 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9171 case Q3TCGEN_ENVIRONMENT:
9174 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9175 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9176 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9177 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9179 dynamicvertex = true;
9180 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9181 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9184 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9188 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9189 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9190 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9191 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9193 dynamicvertex = true;
9194 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9195 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9199 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9203 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9204 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9205 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9206 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9208 dynamicvertex = true;
9209 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9212 // when the model data has no vertex buffer (dynamic mesh), we need to
9214 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9215 batchneed |= BATCHNEED_NOGAPS;
9217 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9218 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9219 // we ensure this by treating the vertex batch as dynamic...
9220 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9224 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9225 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9226 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9227 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9229 dynamicvertex = true;
9234 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9235 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9236 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9237 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9238 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9239 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9240 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9241 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9244 // if needsupdate, we have to do a dynamic vertex batch for sure
9245 if (needsupdate & batchneed)
9249 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9250 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9251 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9252 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9254 dynamicvertex = true;
9257 // see if we need to build vertexmesh from arrays
9258 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9262 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9263 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9264 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9265 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9267 dynamicvertex = true;
9270 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9271 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9272 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9274 rsurface.batchvertex3f = rsurface.modelvertex3f;
9275 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9276 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9277 rsurface.batchsvector3f = rsurface.modelsvector3f;
9278 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9279 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9280 rsurface.batchtvector3f = rsurface.modeltvector3f;
9281 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9282 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9283 rsurface.batchnormal3f = rsurface.modelnormal3f;
9284 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9285 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9286 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9287 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9288 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9289 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9290 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9291 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9292 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9293 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9294 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9295 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9296 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9297 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9298 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9299 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9300 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9301 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9302 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9303 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9304 rsurface.batchelement3i = rsurface.modelelement3i;
9305 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9306 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9307 rsurface.batchelement3s = rsurface.modelelement3s;
9308 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9309 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9310 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9311 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9312 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9313 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9314 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9316 // if any dynamic vertex processing has to occur in software, we copy the
9317 // entire surface list together before processing to rebase the vertices
9318 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9320 // if any gaps exist and we do not have a static vertex buffer, we have to
9321 // copy the surface list together to avoid wasting upload bandwidth on the
9322 // vertices in the gaps.
9324 // if gaps exist and we have a static vertex buffer, we can choose whether
9325 // to combine the index buffer ranges into one dynamic index buffer or
9326 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9328 // in many cases the batch is reduced to one draw call.
9330 rsurface.batchmultidraw = false;
9331 rsurface.batchmultidrawnumsurfaces = 0;
9332 rsurface.batchmultidrawsurfacelist = NULL;
9336 // static vertex data, just set pointers...
9337 rsurface.batchgeneratedvertex = false;
9338 // if there are gaps, we want to build a combined index buffer,
9339 // otherwise use the original static buffer with an appropriate offset
9342 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9343 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9344 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9345 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9346 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9348 rsurface.batchmultidraw = true;
9349 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9350 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9353 // build a new triangle elements array for this batch
9354 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9355 rsurface.batchfirsttriangle = 0;
9357 for (i = 0;i < texturenumsurfaces;i++)
9359 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9360 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9361 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9362 numtriangles += surfacenumtriangles;
9364 rsurface.batchelement3i_indexbuffer = NULL;
9365 rsurface.batchelement3i_bufferoffset = 0;
9366 rsurface.batchelement3s = NULL;
9367 rsurface.batchelement3s_indexbuffer = NULL;
9368 rsurface.batchelement3s_bufferoffset = 0;
9369 if (endvertex <= 65536)
9371 // make a 16bit (unsigned short) index array if possible
9372 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9373 for (i = 0;i < numtriangles*3;i++)
9374 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9376 // upload buffer data for the copytriangles batch
9377 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9379 if (rsurface.batchelement3s)
9380 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9381 else if (rsurface.batchelement3i)
9382 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9387 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9388 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9389 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9390 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9395 // something needs software processing, do it for real...
9396 // we only directly handle separate array data in this case and then
9397 // generate interleaved data if needed...
9398 rsurface.batchgeneratedvertex = true;
9399 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9400 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9401 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9402 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9404 // now copy the vertex data into a combined array and make an index array
9405 // (this is what Quake3 does all the time)
9406 // we also apply any skeletal animation here that would have been done in
9407 // the vertex shader, because most of the dynamic vertex animation cases
9408 // need actual vertex positions and normals
9409 //if (dynamicvertex)
9411 rsurface.batchvertexmesh = NULL;
9412 rsurface.batchvertexmesh_vertexbuffer = NULL;
9413 rsurface.batchvertexmesh_bufferoffset = 0;
9414 rsurface.batchvertex3f = NULL;
9415 rsurface.batchvertex3f_vertexbuffer = NULL;
9416 rsurface.batchvertex3f_bufferoffset = 0;
9417 rsurface.batchsvector3f = NULL;
9418 rsurface.batchsvector3f_vertexbuffer = NULL;
9419 rsurface.batchsvector3f_bufferoffset = 0;
9420 rsurface.batchtvector3f = NULL;
9421 rsurface.batchtvector3f_vertexbuffer = NULL;
9422 rsurface.batchtvector3f_bufferoffset = 0;
9423 rsurface.batchnormal3f = NULL;
9424 rsurface.batchnormal3f_vertexbuffer = NULL;
9425 rsurface.batchnormal3f_bufferoffset = 0;
9426 rsurface.batchlightmapcolor4f = NULL;
9427 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9428 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9429 rsurface.batchtexcoordtexture2f = NULL;
9430 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9431 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9432 rsurface.batchtexcoordlightmap2f = NULL;
9433 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9434 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9435 rsurface.batchskeletalindex4ub = NULL;
9436 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9437 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9438 rsurface.batchskeletalweight4ub = NULL;
9439 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9440 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9441 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9442 rsurface.batchelement3i_indexbuffer = NULL;
9443 rsurface.batchelement3i_bufferoffset = 0;
9444 rsurface.batchelement3s = NULL;
9445 rsurface.batchelement3s_indexbuffer = NULL;
9446 rsurface.batchelement3s_bufferoffset = 0;
9447 rsurface.batchskeletaltransform3x4buffer = NULL;
9448 rsurface.batchskeletaltransform3x4offset = 0;
9449 rsurface.batchskeletaltransform3x4size = 0;
9450 // we'll only be setting up certain arrays as needed
9451 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9452 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9453 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9454 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9455 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9456 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9457 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9459 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9460 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9462 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9463 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9464 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9465 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9466 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9467 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9468 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9470 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9471 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9475 for (i = 0;i < texturenumsurfaces;i++)
9477 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9478 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9479 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9480 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9481 // copy only the data requested
9482 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9483 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9484 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9486 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9488 if (rsurface.batchvertex3f)
9489 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9491 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9493 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9495 if (rsurface.modelnormal3f)
9496 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9498 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9500 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9502 if (rsurface.modelsvector3f)
9504 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9505 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9509 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9510 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9513 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9515 if (rsurface.modellightmapcolor4f)
9516 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9518 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9520 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9522 if (rsurface.modeltexcoordtexture2f)
9523 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9525 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9527 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9529 if (rsurface.modeltexcoordlightmap2f)
9530 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9532 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9534 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9536 if (rsurface.modelskeletalindex4ub)
9538 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9539 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9543 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9544 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9545 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9546 for (j = 0;j < surfacenumvertices;j++)
9551 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9552 numvertices += surfacenumvertices;
9553 numtriangles += surfacenumtriangles;
9556 // generate a 16bit index array as well if possible
9557 // (in general, dynamic batches fit)
9558 if (numvertices <= 65536)
9560 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9561 for (i = 0;i < numtriangles*3;i++)
9562 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9565 // since we've copied everything, the batch now starts at 0
9566 rsurface.batchfirstvertex = 0;
9567 rsurface.batchnumvertices = batchnumvertices;
9568 rsurface.batchfirsttriangle = 0;
9569 rsurface.batchnumtriangles = batchnumtriangles;
9572 // apply skeletal animation that would have been done in the vertex shader
9573 if (rsurface.batchskeletaltransform3x4)
9575 const unsigned char *si;
9576 const unsigned char *sw;
9578 const float *b = rsurface.batchskeletaltransform3x4;
9579 float *vp, *vs, *vt, *vn;
9581 float m[3][4], n[3][4];
9582 float tp[3], ts[3], tt[3], tn[3];
9583 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9584 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9585 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9586 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9587 si = rsurface.batchskeletalindex4ub;
9588 sw = rsurface.batchskeletalweight4ub;
9589 vp = rsurface.batchvertex3f;
9590 vs = rsurface.batchsvector3f;
9591 vt = rsurface.batchtvector3f;
9592 vn = rsurface.batchnormal3f;
9593 memset(m[0], 0, sizeof(m));
9594 memset(n[0], 0, sizeof(n));
9595 for (i = 0;i < batchnumvertices;i++)
9597 t[0] = b + si[0]*12;
9600 // common case - only one matrix
9614 else if (sw[2] + sw[3])
9617 t[1] = b + si[1]*12;
9618 t[2] = b + si[2]*12;
9619 t[3] = b + si[3]*12;
9620 w[0] = sw[0] * (1.0f / 255.0f);
9621 w[1] = sw[1] * (1.0f / 255.0f);
9622 w[2] = sw[2] * (1.0f / 255.0f);
9623 w[3] = sw[3] * (1.0f / 255.0f);
9624 // blend the matrices
9625 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9626 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9627 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9628 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9629 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9630 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9631 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9632 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9633 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9634 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9635 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9636 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9641 t[1] = b + si[1]*12;
9642 w[0] = sw[0] * (1.0f / 255.0f);
9643 w[1] = sw[1] * (1.0f / 255.0f);
9644 // blend the matrices
9645 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9646 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9647 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9648 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9649 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9650 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9651 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9652 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9653 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9654 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9655 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9656 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9660 // modify the vertex
9662 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9663 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9664 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9668 // the normal transformation matrix is a set of cross products...
9669 CrossProduct(m[1], m[2], n[0]);
9670 CrossProduct(m[2], m[0], n[1]);
9671 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9673 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9674 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9675 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9676 VectorNormalize(vn);
9681 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9682 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9683 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9684 VectorNormalize(vs);
9687 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9688 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9689 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9690 VectorNormalize(vt);
9695 rsurface.batchskeletaltransform3x4 = NULL;
9696 rsurface.batchskeletalnumtransforms = 0;
9699 // q1bsp surfaces rendered in vertex color mode have to have colors
9700 // calculated based on lightstyles
9701 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9703 // generate color arrays for the surfaces in this list
9708 const unsigned char *lm;
9709 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9710 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9711 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9713 for (i = 0;i < texturenumsurfaces;i++)
9715 surface = texturesurfacelist[i];
9716 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9717 surfacenumvertices = surface->num_vertices;
9718 if (surface->lightmapinfo->samples)
9720 for (j = 0;j < surfacenumvertices;j++)
9722 lm = surface->lightmapinfo->samples + offsets[j];
9723 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9724 VectorScale(lm, scale, c);
9725 if (surface->lightmapinfo->styles[1] != 255)
9727 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9729 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9730 VectorMA(c, scale, lm, c);
9731 if (surface->lightmapinfo->styles[2] != 255)
9734 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9735 VectorMA(c, scale, lm, c);
9736 if (surface->lightmapinfo->styles[3] != 255)
9739 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9740 VectorMA(c, scale, lm, c);
9747 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);
9753 for (j = 0;j < surfacenumvertices;j++)
9755 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9762 // if vertices are deformed (sprite flares and things in maps, possibly
9763 // water waves, bulges and other deformations), modify the copied vertices
9765 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9768 switch (deform->deform)
9771 case Q3DEFORM_PROJECTIONSHADOW:
9772 case Q3DEFORM_TEXT0:
9773 case Q3DEFORM_TEXT1:
9774 case Q3DEFORM_TEXT2:
9775 case Q3DEFORM_TEXT3:
9776 case Q3DEFORM_TEXT4:
9777 case Q3DEFORM_TEXT5:
9778 case Q3DEFORM_TEXT6:
9779 case Q3DEFORM_TEXT7:
9782 case Q3DEFORM_AUTOSPRITE:
9783 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9784 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9785 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9786 VectorNormalize(newforward);
9787 VectorNormalize(newright);
9788 VectorNormalize(newup);
9789 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9790 // rsurface.batchvertex3f_vertexbuffer = NULL;
9791 // rsurface.batchvertex3f_bufferoffset = 0;
9792 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9793 // rsurface.batchsvector3f_vertexbuffer = NULL;
9794 // rsurface.batchsvector3f_bufferoffset = 0;
9795 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9796 // rsurface.batchtvector3f_vertexbuffer = NULL;
9797 // rsurface.batchtvector3f_bufferoffset = 0;
9798 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9799 // rsurface.batchnormal3f_vertexbuffer = NULL;
9800 // rsurface.batchnormal3f_bufferoffset = 0;
9801 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9802 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9803 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9804 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9805 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);
9806 // a single autosprite surface can contain multiple sprites...
9807 for (j = 0;j < batchnumvertices - 3;j += 4)
9809 VectorClear(center);
9810 for (i = 0;i < 4;i++)
9811 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9812 VectorScale(center, 0.25f, center);
9813 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9814 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9815 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9816 for (i = 0;i < 4;i++)
9818 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9819 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9822 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9823 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9824 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);
9826 case Q3DEFORM_AUTOSPRITE2:
9827 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9828 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9829 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9830 VectorNormalize(newforward);
9831 VectorNormalize(newright);
9832 VectorNormalize(newup);
9833 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9834 // rsurface.batchvertex3f_vertexbuffer = NULL;
9835 // rsurface.batchvertex3f_bufferoffset = 0;
9837 const float *v1, *v2;
9847 memset(shortest, 0, sizeof(shortest));
9848 // a single autosprite surface can contain multiple sprites...
9849 for (j = 0;j < batchnumvertices - 3;j += 4)
9851 VectorClear(center);
9852 for (i = 0;i < 4;i++)
9853 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9854 VectorScale(center, 0.25f, center);
9855 // find the two shortest edges, then use them to define the
9856 // axis vectors for rotating around the central axis
9857 for (i = 0;i < 6;i++)
9859 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9860 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9861 l = VectorDistance2(v1, v2);
9862 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9864 l += (1.0f / 1024.0f);
9865 if (shortest[0].length2 > l || i == 0)
9867 shortest[1] = shortest[0];
9868 shortest[0].length2 = l;
9869 shortest[0].v1 = v1;
9870 shortest[0].v2 = v2;
9872 else if (shortest[1].length2 > l || i == 1)
9874 shortest[1].length2 = l;
9875 shortest[1].v1 = v1;
9876 shortest[1].v2 = v2;
9879 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9880 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9881 // this calculates the right vector from the shortest edge
9882 // and the up vector from the edge midpoints
9883 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9884 VectorNormalize(right);
9885 VectorSubtract(end, start, up);
9886 VectorNormalize(up);
9887 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9888 VectorSubtract(rsurface.localvieworigin, center, forward);
9889 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9890 VectorNegate(forward, forward);
9891 VectorReflect(forward, 0, up, forward);
9892 VectorNormalize(forward);
9893 CrossProduct(up, forward, newright);
9894 VectorNormalize(newright);
9895 // rotate the quad around the up axis vector, this is made
9896 // especially easy by the fact we know the quad is flat,
9897 // so we only have to subtract the center position and
9898 // measure distance along the right vector, and then
9899 // multiply that by the newright vector and add back the
9901 // we also need to subtract the old position to undo the
9902 // displacement from the center, which we do with a
9903 // DotProduct, the subtraction/addition of center is also
9904 // optimized into DotProducts here
9905 l = DotProduct(right, center);
9906 for (i = 0;i < 4;i++)
9908 v1 = rsurface.batchvertex3f + 3*(j+i);
9909 f = DotProduct(right, v1) - l;
9910 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9914 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9916 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9917 // rsurface.batchnormal3f_vertexbuffer = NULL;
9918 // rsurface.batchnormal3f_bufferoffset = 0;
9919 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9921 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9923 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9924 // rsurface.batchsvector3f_vertexbuffer = NULL;
9925 // rsurface.batchsvector3f_bufferoffset = 0;
9926 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9927 // rsurface.batchtvector3f_vertexbuffer = NULL;
9928 // rsurface.batchtvector3f_bufferoffset = 0;
9929 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);
9932 case Q3DEFORM_NORMAL:
9933 // deform the normals to make reflections wavey
9934 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9935 rsurface.batchnormal3f_vertexbuffer = NULL;
9936 rsurface.batchnormal3f_bufferoffset = 0;
9937 for (j = 0;j < batchnumvertices;j++)
9940 float *normal = rsurface.batchnormal3f + 3*j;
9941 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9942 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9943 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9944 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9945 VectorNormalize(normal);
9947 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9949 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9950 // rsurface.batchsvector3f_vertexbuffer = NULL;
9951 // rsurface.batchsvector3f_bufferoffset = 0;
9952 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9953 // rsurface.batchtvector3f_vertexbuffer = NULL;
9954 // rsurface.batchtvector3f_bufferoffset = 0;
9955 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);
9959 // deform vertex array to make wavey water and flags and such
9960 waveparms[0] = deform->waveparms[0];
9961 waveparms[1] = deform->waveparms[1];
9962 waveparms[2] = deform->waveparms[2];
9963 waveparms[3] = deform->waveparms[3];
9964 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9965 break; // if wavefunc is a nop, don't make a dynamic vertex array
9966 // this is how a divisor of vertex influence on deformation
9967 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9968 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9969 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9970 // rsurface.batchvertex3f_vertexbuffer = NULL;
9971 // rsurface.batchvertex3f_bufferoffset = 0;
9972 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9973 // rsurface.batchnormal3f_vertexbuffer = NULL;
9974 // rsurface.batchnormal3f_bufferoffset = 0;
9975 for (j = 0;j < batchnumvertices;j++)
9977 // if the wavefunc depends on time, evaluate it per-vertex
9980 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9981 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9983 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9985 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9986 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9987 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9989 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 // rsurface.batchsvector3f_vertexbuffer = NULL;
9991 // rsurface.batchsvector3f_bufferoffset = 0;
9992 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9993 // rsurface.batchtvector3f_vertexbuffer = NULL;
9994 // rsurface.batchtvector3f_bufferoffset = 0;
9995 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);
9998 case Q3DEFORM_BULGE:
9999 // deform vertex array to make the surface have moving bulges
10000 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10001 // rsurface.batchvertex3f_vertexbuffer = NULL;
10002 // rsurface.batchvertex3f_bufferoffset = 0;
10003 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10004 // rsurface.batchnormal3f_vertexbuffer = NULL;
10005 // rsurface.batchnormal3f_bufferoffset = 0;
10006 for (j = 0;j < batchnumvertices;j++)
10008 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10009 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10011 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10012 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10013 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10015 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10016 // rsurface.batchsvector3f_vertexbuffer = NULL;
10017 // rsurface.batchsvector3f_bufferoffset = 0;
10018 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10019 // rsurface.batchtvector3f_vertexbuffer = NULL;
10020 // rsurface.batchtvector3f_bufferoffset = 0;
10021 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);
10024 case Q3DEFORM_MOVE:
10025 // deform vertex array
10026 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10027 break; // if wavefunc is a nop, don't make a dynamic vertex array
10028 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10029 VectorScale(deform->parms, scale, waveparms);
10030 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10031 // rsurface.batchvertex3f_vertexbuffer = NULL;
10032 // rsurface.batchvertex3f_bufferoffset = 0;
10033 for (j = 0;j < batchnumvertices;j++)
10034 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10039 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10041 // generate texcoords based on the chosen texcoord source
10042 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10045 case Q3TCGEN_TEXTURE:
10047 case Q3TCGEN_LIGHTMAP:
10048 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10049 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10050 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10051 if (rsurface.batchtexcoordlightmap2f)
10052 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10054 case Q3TCGEN_VECTOR:
10055 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10056 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10057 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10058 for (j = 0;j < batchnumvertices;j++)
10060 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10061 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10064 case Q3TCGEN_ENVIRONMENT:
10065 // make environment reflections using a spheremap
10066 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10067 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10068 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10069 for (j = 0;j < batchnumvertices;j++)
10071 // identical to Q3A's method, but executed in worldspace so
10072 // carried models can be shiny too
10074 float viewer[3], d, reflected[3], worldreflected[3];
10076 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10077 // VectorNormalize(viewer);
10079 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10081 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10082 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10083 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10084 // note: this is proportinal to viewer, so we can normalize later
10086 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10087 VectorNormalize(worldreflected);
10089 // note: this sphere map only uses world x and z!
10090 // so positive and negative y will LOOK THE SAME.
10091 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10092 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10096 // the only tcmod that needs software vertex processing is turbulent, so
10097 // check for it here and apply the changes if needed
10098 // and we only support that as the first one
10099 // (handling a mixture of turbulent and other tcmods would be problematic
10100 // without punting it entirely to a software path)
10101 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10103 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10104 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10105 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10106 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10107 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10108 for (j = 0;j < batchnumvertices;j++)
10110 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);
10111 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10116 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10118 // convert the modified arrays to vertex structs
10119 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10120 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10121 // rsurface.batchvertexmesh_bufferoffset = 0;
10122 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10123 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10124 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10125 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10126 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10127 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10128 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10130 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10132 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10133 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10136 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10137 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10138 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10139 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10140 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10141 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10142 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10143 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10144 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10145 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10147 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10149 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10150 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10155 // upload buffer data for the dynamic batch
10156 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10158 if (rsurface.batchvertexmesh)
10159 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10162 if (rsurface.batchvertex3f)
10163 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10164 if (rsurface.batchsvector3f)
10165 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10166 if (rsurface.batchtvector3f)
10167 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10168 if (rsurface.batchnormal3f)
10169 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10170 if (rsurface.batchlightmapcolor4f)
10171 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10172 if (rsurface.batchtexcoordtexture2f)
10173 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10174 if (rsurface.batchtexcoordlightmap2f)
10175 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10176 if (rsurface.batchskeletalindex4ub)
10177 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10178 if (rsurface.batchskeletalweight4ub)
10179 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10181 if (rsurface.batchelement3s)
10182 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10183 else if (rsurface.batchelement3i)
10184 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10188 void RSurf_DrawBatch(void)
10190 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10191 // through the pipeline, killing it earlier in the pipeline would have
10192 // per-surface overhead rather than per-batch overhead, so it's best to
10193 // reject it here, before it hits glDraw.
10194 if (rsurface.batchnumtriangles == 0)
10197 // batch debugging code
10198 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10204 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10205 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10208 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10210 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10212 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10213 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);
10220 if (rsurface.batchmultidraw)
10222 // issue multiple draws rather than copying index data
10223 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10224 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10225 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10226 for (i = 0;i < numsurfaces;)
10228 // combine consecutive surfaces as one draw
10229 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10230 if (surfacelist[j] != surfacelist[k] + 1)
10232 firstvertex = surfacelist[i]->num_firstvertex;
10233 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10234 firsttriangle = surfacelist[i]->num_firsttriangle;
10235 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10236 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);
10242 // there is only one consecutive run of index data (may have been combined)
10243 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);
10247 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10249 // pick the closest matching water plane
10250 int planeindex, vertexindex, bestplaneindex = -1;
10254 r_waterstate_waterplane_t *p;
10255 qboolean prepared = false;
10257 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10259 if(p->camera_entity != rsurface.texture->camera_entity)
10264 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10266 if(rsurface.batchnumvertices == 0)
10269 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10271 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10272 d += fabs(PlaneDiff(vert, &p->plane));
10274 if (bestd > d || bestplaneindex < 0)
10277 bestplaneindex = planeindex;
10280 return bestplaneindex;
10281 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10282 // this situation though, as it might be better to render single larger
10283 // batches with useless stuff (backface culled for example) than to
10284 // render multiple smaller batches
10287 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10290 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10291 rsurface.passcolor4f_vertexbuffer = 0;
10292 rsurface.passcolor4f_bufferoffset = 0;
10293 for (i = 0;i < rsurface.batchnumvertices;i++)
10294 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10297 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10304 if (rsurface.passcolor4f)
10306 // generate color arrays
10307 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10308 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10309 rsurface.passcolor4f_vertexbuffer = 0;
10310 rsurface.passcolor4f_bufferoffset = 0;
10311 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
10313 f = RSurf_FogVertex(v);
10322 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10323 rsurface.passcolor4f_vertexbuffer = 0;
10324 rsurface.passcolor4f_bufferoffset = 0;
10325 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10327 f = RSurf_FogVertex(v);
10336 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10343 if (!rsurface.passcolor4f)
10345 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10346 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10347 rsurface.passcolor4f_vertexbuffer = 0;
10348 rsurface.passcolor4f_bufferoffset = 0;
10349 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)
10351 f = RSurf_FogVertex(v);
10352 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10353 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10354 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10359 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10364 if (!rsurface.passcolor4f)
10366 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10367 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10368 rsurface.passcolor4f_vertexbuffer = 0;
10369 rsurface.passcolor4f_bufferoffset = 0;
10370 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10379 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10384 if (!rsurface.passcolor4f)
10386 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10387 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10388 rsurface.passcolor4f_vertexbuffer = 0;
10389 rsurface.passcolor4f_bufferoffset = 0;
10390 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10392 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10393 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10394 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10399 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10402 rsurface.passcolor4f = NULL;
10403 rsurface.passcolor4f_vertexbuffer = 0;
10404 rsurface.passcolor4f_bufferoffset = 0;
10405 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10406 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10407 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10408 GL_Color(r, g, b, a);
10409 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10410 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10411 R_Mesh_TexMatrix(0, NULL);
10415 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10417 // TODO: optimize applyfog && applycolor case
10418 // just apply fog if necessary, and tint the fog color array if necessary
10419 rsurface.passcolor4f = NULL;
10420 rsurface.passcolor4f_vertexbuffer = 0;
10421 rsurface.passcolor4f_bufferoffset = 0;
10422 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10423 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10424 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10425 GL_Color(r, g, b, a);
10429 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10432 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10433 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10434 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10435 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10436 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10437 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10438 GL_Color(r, g, b, a);
10442 static void RSurf_DrawBatch_GL11_ClampColor(void)
10447 if (!rsurface.passcolor4f)
10449 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10451 c2[0] = bound(0.0f, c1[0], 1.0f);
10452 c2[1] = bound(0.0f, c1[1], 1.0f);
10453 c2[2] = bound(0.0f, c1[2], 1.0f);
10454 c2[3] = bound(0.0f, c1[3], 1.0f);
10458 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10468 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10469 rsurface.passcolor4f_vertexbuffer = 0;
10470 rsurface.passcolor4f_bufferoffset = 0;
10471 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)
10473 f = -DotProduct(r_refdef.view.forward, n);
10475 f = f * 0.85 + 0.15; // work around so stuff won't get black
10476 f *= fakelightintensity;
10477 Vector4Set(c, f, f, f, 1);
10481 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10483 RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10484 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10485 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10486 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10487 GL_Color(r, g, b, a);
10491 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10499 vec3_t ambientcolor;
10500 vec3_t diffusecolor;
10504 VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10505 f = 0.5f * lightmapintensity;
10506 ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10507 ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10508 ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10509 diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10510 diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10511 diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10513 if (VectorLength2(diffusecolor) > 0)
10515 // q3-style directional shading
10516 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10517 rsurface.passcolor4f_vertexbuffer = 0;
10518 rsurface.passcolor4f_bufferoffset = 0;
10519 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)
10521 if ((f = DotProduct(n, lightdir)) > 0)
10522 VectorMA(ambientcolor, f, diffusecolor, c);
10524 VectorCopy(ambientcolor, c);
10531 *applycolor = false;
10535 *r = ambientcolor[0];
10536 *g = ambientcolor[1];
10537 *b = ambientcolor[2];
10538 rsurface.passcolor4f = NULL;
10539 rsurface.passcolor4f_vertexbuffer = 0;
10540 rsurface.passcolor4f_bufferoffset = 0;
10544 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10546 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10547 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10548 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10549 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10550 GL_Color(r, g, b, a);
10554 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10562 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10563 rsurface.passcolor4f_vertexbuffer = 0;
10564 rsurface.passcolor4f_bufferoffset = 0;
10566 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10568 f = 1 - RSurf_FogVertex(v);
10576 void RSurf_SetupDepthAndCulling(void)
10578 // submodels are biased to avoid z-fighting with world surfaces that they
10579 // may be exactly overlapping (avoids z-fighting artifacts on certain
10580 // doors and things in Quake maps)
10581 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10582 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10583 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10584 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10587 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10590 // transparent sky would be ridiculous
10591 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10593 R_SetupShader_Generic_NoTexture(false, false);
10594 skyrenderlater = true;
10595 RSurf_SetupDepthAndCulling();
10596 GL_DepthMask(true);
10598 // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10599 if (r_sky_scissor.integer)
10601 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10602 for (i = 0; i < texturenumsurfaces; i++)
10604 const msurface_t *surf = texturesurfacelist[i];
10607 float mins[3], maxs[3];
10609 for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10611 Matrix4x4_Transform(&rsurface.matrix, v, p);
10614 if (mins[0] > p[0]) mins[0] = p[0];
10615 if (mins[1] > p[1]) mins[1] = p[1];
10616 if (mins[2] > p[2]) mins[2] = p[2];
10617 if (maxs[0] < p[0]) maxs[0] = p[0];
10618 if (maxs[1] < p[1]) maxs[1] = p[1];
10619 if (maxs[2] < p[2]) maxs[2] = p[2];
10623 VectorCopy(p, mins);
10624 VectorCopy(p, maxs);
10627 if (!R_ScissorForBBox(mins, maxs, scissor))
10631 if (skyscissor[0] > scissor[0])
10633 skyscissor[2] += skyscissor[0] - scissor[0];
10634 skyscissor[0] = scissor[0];
10636 if (skyscissor[1] > scissor[1])
10638 skyscissor[3] += skyscissor[1] - scissor[1];
10639 skyscissor[1] = scissor[1];
10641 if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10642 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10643 if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10644 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10647 Vector4Copy(scissor, skyscissor);
10652 // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10653 // skymasking on them, and Quake3 never did sky masking (unlike
10654 // software Quake and software Quake2), so disable the sky masking
10655 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10656 // and skymasking also looks very bad when noclipping outside the
10657 // level, so don't use it then either.
10658 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)
10660 R_Mesh_ResetTextureState();
10661 if (skyrendermasked)
10663 R_SetupShader_DepthOrShadow(false, false, false);
10664 // depth-only (masking)
10665 GL_ColorMask(0, 0, 0, 0);
10666 // just to make sure that braindead drivers don't draw
10667 // anything despite that colormask...
10668 GL_BlendFunc(GL_ZERO, GL_ONE);
10669 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10670 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10674 R_SetupShader_Generic_NoTexture(false, false);
10676 GL_BlendFunc(GL_ONE, GL_ZERO);
10677 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10678 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10679 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10682 if (skyrendermasked)
10683 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10685 R_Mesh_ResetTextureState();
10686 GL_Color(1, 1, 1, 1);
10689 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10690 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10691 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10693 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10697 // render screenspace normalmap to texture
10698 GL_DepthMask(true);
10699 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10704 // bind lightmap texture
10706 // water/refraction/reflection/camera surfaces have to be handled specially
10707 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10709 int start, end, startplaneindex;
10710 for (start = 0;start < texturenumsurfaces;start = end)
10712 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10713 if(startplaneindex < 0)
10715 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10716 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10720 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10722 // now that we have a batch using the same planeindex, render it
10723 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10725 // render water or distortion background
10726 GL_DepthMask(true);
10727 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10729 // blend surface on top
10730 GL_DepthMask(false);
10731 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10734 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10736 // render surface with reflection texture as input
10737 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10738 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10745 // render surface batch normally
10746 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10747 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10751 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10753 // OpenGL 1.3 path - anything not completely ancient
10754 qboolean applycolor;
10757 const texturelayer_t *layer;
10758 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10759 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10761 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10764 int layertexrgbscale;
10765 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10767 if (layerindex == 0)
10768 GL_AlphaTest(true);
10771 GL_AlphaTest(false);
10772 GL_DepthFunc(GL_EQUAL);
10775 GL_DepthMask(layer->depthmask && writedepth);
10776 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10777 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10779 layertexrgbscale = 4;
10780 VectorScale(layer->color, 0.25f, layercolor);
10782 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10784 layertexrgbscale = 2;
10785 VectorScale(layer->color, 0.5f, layercolor);
10789 layertexrgbscale = 1;
10790 VectorScale(layer->color, 1.0f, layercolor);
10792 layercolor[3] = layer->color[3];
10793 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10794 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10795 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10796 switch (layer->type)
10798 case TEXTURELAYERTYPE_LITTEXTURE:
10799 // single-pass lightmapped texture with 2x rgbscale
10800 R_Mesh_TexBind(0, r_texture_white);
10801 R_Mesh_TexMatrix(0, NULL);
10802 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10803 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10804 R_Mesh_TexBind(1, layer->texture);
10805 R_Mesh_TexMatrix(1, &layer->texmatrix);
10806 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10807 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10808 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10809 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10810 else if (FAKELIGHT_ENABLED)
10811 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10812 else if (rsurface.uselightmaptexture)
10813 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10815 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10817 case TEXTURELAYERTYPE_TEXTURE:
10818 // singletexture unlit texture with transparency support
10819 R_Mesh_TexBind(0, layer->texture);
10820 R_Mesh_TexMatrix(0, &layer->texmatrix);
10821 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10822 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10823 R_Mesh_TexBind(1, 0);
10824 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10825 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10827 case TEXTURELAYERTYPE_FOG:
10828 // singletexture fogging
10829 if (layer->texture)
10831 R_Mesh_TexBind(0, layer->texture);
10832 R_Mesh_TexMatrix(0, &layer->texmatrix);
10833 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10834 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10838 R_Mesh_TexBind(0, 0);
10839 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10841 R_Mesh_TexBind(1, 0);
10842 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10843 // generate a color array for the fog pass
10844 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10845 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10849 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10852 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10854 GL_DepthFunc(GL_LEQUAL);
10855 GL_AlphaTest(false);
10859 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10861 // OpenGL 1.1 - crusty old voodoo path
10864 const texturelayer_t *layer;
10865 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10866 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10868 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10870 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10872 if (layerindex == 0)
10873 GL_AlphaTest(true);
10876 GL_AlphaTest(false);
10877 GL_DepthFunc(GL_EQUAL);
10880 GL_DepthMask(layer->depthmask && writedepth);
10881 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10882 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10883 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10884 switch (layer->type)
10886 case TEXTURELAYERTYPE_LITTEXTURE:
10887 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10889 // two-pass lit texture with 2x rgbscale
10890 // first the lightmap pass
10891 R_Mesh_TexBind(0, r_texture_white);
10892 R_Mesh_TexMatrix(0, NULL);
10893 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10894 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10895 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10896 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10897 else if (FAKELIGHT_ENABLED)
10898 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10899 else if (rsurface.uselightmaptexture)
10900 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10902 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10903 // then apply the texture to it
10904 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10905 R_Mesh_TexBind(0, layer->texture);
10906 R_Mesh_TexMatrix(0, &layer->texmatrix);
10907 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10908 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10909 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);
10913 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10914 R_Mesh_TexBind(0, layer->texture);
10915 R_Mesh_TexMatrix(0, &layer->texmatrix);
10916 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10917 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10918 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10919 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);
10920 else if (FAKELIGHT_ENABLED)
10921 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);
10923 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);
10926 case TEXTURELAYERTYPE_TEXTURE:
10927 // singletexture unlit texture with transparency support
10928 R_Mesh_TexBind(0, layer->texture);
10929 R_Mesh_TexMatrix(0, &layer->texmatrix);
10930 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10931 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10932 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);
10934 case TEXTURELAYERTYPE_FOG:
10935 // singletexture fogging
10936 if (layer->texture)
10938 R_Mesh_TexBind(0, layer->texture);
10939 R_Mesh_TexMatrix(0, &layer->texmatrix);
10940 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10941 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10945 R_Mesh_TexBind(0, 0);
10946 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10948 // generate a color array for the fog pass
10949 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10950 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10954 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10957 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10959 GL_DepthFunc(GL_LEQUAL);
10960 GL_AlphaTest(false);
10964 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10968 r_vertexgeneric_t *batchvertex;
10970 texture_t *t = rsurface.texture;
10972 // R_Mesh_ResetTextureState();
10973 R_SetupShader_Generic_NoTexture(false, false);
10975 if(t && t->currentskinframe)
10977 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10978 c[3] *= t->currentalpha;
10988 if (t->pantstexture || t->shirttexture)
10990 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10991 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10992 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10995 // brighten it up (as texture value 127 means "unlit")
10996 c[0] *= 2 * r_refdef.view.colorscale;
10997 c[1] *= 2 * r_refdef.view.colorscale;
10998 c[2] *= 2 * r_refdef.view.colorscale;
11000 if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11001 c[3] *= r_wateralpha.value;
11003 if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11005 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11006 GL_DepthMask(false);
11008 else if(t->currentmaterialflags & MATERIALFLAG_ADD)
11010 GL_BlendFunc(GL_ONE, GL_ONE);
11011 GL_DepthMask(false);
11013 else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11015 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11016 GL_DepthMask(false);
11018 else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11020 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
11021 GL_DepthMask(false);
11025 GL_BlendFunc(GL_ONE, GL_ZERO);
11026 GL_DepthMask(writedepth);
11029 if (r_showsurfaces.integer == 3)
11031 rsurface.passcolor4f = NULL;
11033 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11035 qboolean applycolor = true;
11038 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11040 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
11042 else if (FAKELIGHT_ENABLED)
11044 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11046 RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
11050 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11053 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11054 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11055 RSurf_DrawBatch_GL11_ApplyAmbient();
11058 if(!rsurface.passcolor4f)
11059 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11061 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11062 if(r_refdef.fogenabled)
11063 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11064 RSurf_DrawBatch_GL11_ClampColor();
11066 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11067 R_SetupShader_Generic_NoTexture(false, false);
11070 else if (!r_refdef.view.showdebug)
11072 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11073 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11074 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11076 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11077 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11079 R_Mesh_PrepareVertices_Generic_Unlock();
11082 else if (r_showsurfaces.integer == 4)
11084 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11085 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11086 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11088 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11089 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11090 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11092 R_Mesh_PrepareVertices_Generic_Unlock();
11095 else if (r_showsurfaces.integer == 2)
11098 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11099 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11100 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11102 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11103 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11104 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11105 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11106 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11107 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11108 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11110 R_Mesh_PrepareVertices_Generic_Unlock();
11111 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11115 int texturesurfaceindex;
11117 const msurface_t *surface;
11118 float surfacecolor4f[4];
11119 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11120 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11122 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11124 surface = texturesurfacelist[texturesurfaceindex];
11125 k = (int)(((size_t)surface) / sizeof(msurface_t));
11126 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11127 for (j = 0;j < surface->num_vertices;j++)
11129 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11130 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11134 R_Mesh_PrepareVertices_Generic_Unlock();
11139 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11142 RSurf_SetupDepthAndCulling();
11143 if (r_showsurfaces.integer)
11145 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11148 switch (vid.renderpath)
11150 case RENDERPATH_GL20:
11151 case RENDERPATH_D3D9:
11152 case RENDERPATH_D3D10:
11153 case RENDERPATH_D3D11:
11154 case RENDERPATH_SOFT:
11155 case RENDERPATH_GLES2:
11156 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11158 case RENDERPATH_GL13:
11159 case RENDERPATH_GLES1:
11160 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11162 case RENDERPATH_GL11:
11163 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11169 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11172 int texturenumsurfaces, endsurface;
11173 texture_t *texture;
11174 const msurface_t *surface;
11175 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11177 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11178 RSurf_ActiveModelEntity(ent, false, false, false);
11181 switch (vid.renderpath)
11183 case RENDERPATH_GL20:
11184 case RENDERPATH_D3D9:
11185 case RENDERPATH_D3D10:
11186 case RENDERPATH_D3D11:
11187 case RENDERPATH_SOFT:
11188 case RENDERPATH_GLES2:
11189 RSurf_ActiveModelEntity(ent, true, true, false);
11191 case RENDERPATH_GL11:
11192 case RENDERPATH_GL13:
11193 case RENDERPATH_GLES1:
11194 RSurf_ActiveModelEntity(ent, true, false, false);
11199 if (r_transparentdepthmasking.integer)
11201 qboolean setup = false;
11202 for (i = 0;i < numsurfaces;i = j)
11205 surface = rsurface.modelsurfaces + surfacelist[i];
11206 texture = surface->texture;
11207 rsurface.texture = R_GetCurrentTexture(texture);
11208 rsurface.lightmaptexture = NULL;
11209 rsurface.deluxemaptexture = NULL;
11210 rsurface.uselightmaptexture = false;
11211 // scan ahead until we find a different texture
11212 endsurface = min(i + 1024, numsurfaces);
11213 texturenumsurfaces = 0;
11214 texturesurfacelist[texturenumsurfaces++] = surface;
11215 for (;j < endsurface;j++)
11217 surface = rsurface.modelsurfaces + surfacelist[j];
11218 if (texture != surface->texture)
11220 texturesurfacelist[texturenumsurfaces++] = surface;
11222 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11224 // render the range of surfaces as depth
11228 GL_ColorMask(0,0,0,0);
11230 GL_DepthTest(true);
11231 GL_BlendFunc(GL_ONE, GL_ZERO);
11232 GL_DepthMask(true);
11233 // R_Mesh_ResetTextureState();
11235 RSurf_SetupDepthAndCulling();
11236 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11237 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11238 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11242 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11245 for (i = 0;i < numsurfaces;i = j)
11248 surface = rsurface.modelsurfaces + surfacelist[i];
11249 texture = surface->texture;
11250 rsurface.texture = R_GetCurrentTexture(texture);
11251 // scan ahead until we find a different texture
11252 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11253 texturenumsurfaces = 0;
11254 texturesurfacelist[texturenumsurfaces++] = surface;
11255 if(FAKELIGHT_ENABLED)
11257 rsurface.lightmaptexture = NULL;
11258 rsurface.deluxemaptexture = NULL;
11259 rsurface.uselightmaptexture = false;
11260 for (;j < endsurface;j++)
11262 surface = rsurface.modelsurfaces + surfacelist[j];
11263 if (texture != surface->texture)
11265 texturesurfacelist[texturenumsurfaces++] = surface;
11270 rsurface.lightmaptexture = surface->lightmaptexture;
11271 rsurface.deluxemaptexture = surface->deluxemaptexture;
11272 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11273 for (;j < endsurface;j++)
11275 surface = rsurface.modelsurfaces + surfacelist[j];
11276 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11278 texturesurfacelist[texturenumsurfaces++] = surface;
11281 // render the range of surfaces
11282 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11284 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11287 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11289 // transparent surfaces get pushed off into the transparent queue
11290 int surfacelistindex;
11291 const msurface_t *surface;
11292 vec3_t tempcenter, center;
11293 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11295 surface = texturesurfacelist[surfacelistindex];
11296 if (r_transparent_sortsurfacesbynearest.integer)
11298 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11299 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11300 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11304 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11305 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11306 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11308 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11309 if (rsurface.entity->transparent_offset) // transparent offset
11311 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11312 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11313 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11315 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);
11319 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11321 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11323 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11325 RSurf_SetupDepthAndCulling();
11326 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11327 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11328 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11332 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11336 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11339 if (!rsurface.texture->currentnumlayers)
11341 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11342 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11344 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11346 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11347 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11348 else if (!rsurface.texture->currentnumlayers)
11350 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11352 // in the deferred case, transparent surfaces were queued during prepass
11353 if (!r_shadow_usingdeferredprepass)
11354 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11358 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11359 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11364 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11367 texture_t *texture;
11368 R_FrameData_SetMark();
11369 // break the surface list down into batches by texture and use of lightmapping
11370 for (i = 0;i < numsurfaces;i = j)
11373 // texture is the base texture pointer, rsurface.texture is the
11374 // current frame/skin the texture is directing us to use (for example
11375 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11376 // use skin 1 instead)
11377 texture = surfacelist[i]->texture;
11378 rsurface.texture = R_GetCurrentTexture(texture);
11379 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11381 // if this texture is not the kind we want, skip ahead to the next one
11382 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11386 if(FAKELIGHT_ENABLED || depthonly || prepass)
11388 rsurface.lightmaptexture = NULL;
11389 rsurface.deluxemaptexture = NULL;
11390 rsurface.uselightmaptexture = false;
11391 // simply scan ahead until we find a different texture or lightmap state
11392 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11397 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11398 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11399 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11400 // simply scan ahead until we find a different texture or lightmap state
11401 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11404 // render the range of surfaces
11405 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11407 R_FrameData_ReturnToMark();
11410 float locboxvertex3f[6*4*3] =
11412 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11413 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11414 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11415 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11416 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11417 1,0,0, 0,0,0, 0,1,0, 1,1,0
11420 unsigned short locboxelements[6*2*3] =
11425 12,13,14, 12,14,15,
11426 16,17,18, 16,18,19,
11430 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11433 cl_locnode_t *loc = (cl_locnode_t *)ent;
11435 float vertex3f[6*4*3];
11437 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11438 GL_DepthMask(false);
11439 GL_DepthRange(0, 1);
11440 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11441 GL_DepthTest(true);
11442 GL_CullFace(GL_NONE);
11443 R_EntityMatrix(&identitymatrix);
11445 // R_Mesh_ResetTextureState();
11447 i = surfacelist[0];
11448 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11449 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11450 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11451 surfacelist[0] < 0 ? 0.5f : 0.125f);
11453 if (VectorCompare(loc->mins, loc->maxs))
11455 VectorSet(size, 2, 2, 2);
11456 VectorMA(loc->mins, -0.5f, size, mins);
11460 VectorCopy(loc->mins, mins);
11461 VectorSubtract(loc->maxs, loc->mins, size);
11464 for (i = 0;i < 6*4*3;)
11465 for (j = 0;j < 3;j++, i++)
11466 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11468 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11469 R_SetupShader_Generic_NoTexture(false, false);
11470 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11473 void R_DrawLocs(void)
11476 cl_locnode_t *loc, *nearestloc;
11478 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11479 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11481 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11482 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11486 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11488 if (decalsystem->decals)
11489 Mem_Free(decalsystem->decals);
11490 memset(decalsystem, 0, sizeof(*decalsystem));
11493 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)
11496 tridecal_t *decals;
11499 // expand or initialize the system
11500 if (decalsystem->maxdecals <= decalsystem->numdecals)
11502 decalsystem_t old = *decalsystem;
11503 qboolean useshortelements;
11504 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11505 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11506 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)));
11507 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11508 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11509 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11510 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11511 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11512 if (decalsystem->numdecals)
11513 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11515 Mem_Free(old.decals);
11516 for (i = 0;i < decalsystem->maxdecals*3;i++)
11517 decalsystem->element3i[i] = i;
11518 if (useshortelements)
11519 for (i = 0;i < decalsystem->maxdecals*3;i++)
11520 decalsystem->element3s[i] = i;
11523 // grab a decal and search for another free slot for the next one
11524 decals = decalsystem->decals;
11525 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11526 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11528 decalsystem->freedecal = i;
11529 if (decalsystem->numdecals <= i)
11530 decalsystem->numdecals = i + 1;
11532 // initialize the decal
11534 decal->triangleindex = triangleindex;
11535 decal->surfaceindex = surfaceindex;
11536 decal->decalsequence = decalsequence;
11537 decal->color4f[0][0] = c0[0];
11538 decal->color4f[0][1] = c0[1];
11539 decal->color4f[0][2] = c0[2];
11540 decal->color4f[0][3] = 1;
11541 decal->color4f[1][0] = c1[0];
11542 decal->color4f[1][1] = c1[1];
11543 decal->color4f[1][2] = c1[2];
11544 decal->color4f[1][3] = 1;
11545 decal->color4f[2][0] = c2[0];
11546 decal->color4f[2][1] = c2[1];
11547 decal->color4f[2][2] = c2[2];
11548 decal->color4f[2][3] = 1;
11549 decal->vertex3f[0][0] = v0[0];
11550 decal->vertex3f[0][1] = v0[1];
11551 decal->vertex3f[0][2] = v0[2];
11552 decal->vertex3f[1][0] = v1[0];
11553 decal->vertex3f[1][1] = v1[1];
11554 decal->vertex3f[1][2] = v1[2];
11555 decal->vertex3f[2][0] = v2[0];
11556 decal->vertex3f[2][1] = v2[1];
11557 decal->vertex3f[2][2] = v2[2];
11558 decal->texcoord2f[0][0] = t0[0];
11559 decal->texcoord2f[0][1] = t0[1];
11560 decal->texcoord2f[1][0] = t1[0];
11561 decal->texcoord2f[1][1] = t1[1];
11562 decal->texcoord2f[2][0] = t2[0];
11563 decal->texcoord2f[2][1] = t2[1];
11564 TriangleNormal(v0, v1, v2, decal->plane);
11565 VectorNormalize(decal->plane);
11566 decal->plane[3] = DotProduct(v0, decal->plane);
11569 extern cvar_t cl_decals_bias;
11570 extern cvar_t cl_decals_models;
11571 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11572 // baseparms, parms, temps
11573 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)
11578 const float *vertex3f;
11579 const float *normal3f;
11581 float points[2][9][3];
11588 e = rsurface.modelelement3i + 3*triangleindex;
11590 vertex3f = rsurface.modelvertex3f;
11591 normal3f = rsurface.modelnormal3f;
11595 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11597 index = 3*e[cornerindex];
11598 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11603 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11605 index = 3*e[cornerindex];
11606 VectorCopy(vertex3f + index, v[cornerindex]);
11611 //TriangleNormal(v[0], v[1], v[2], normal);
11612 //if (DotProduct(normal, localnormal) < 0.0f)
11614 // clip by each of the box planes formed from the projection matrix
11615 // if anything survives, we emit the decal
11616 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]);
11619 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]);
11622 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]);
11625 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]);
11628 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]);
11631 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]);
11634 // some part of the triangle survived, so we have to accept it...
11637 // dynamic always uses the original triangle
11639 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11641 index = 3*e[cornerindex];
11642 VectorCopy(vertex3f + index, v[cornerindex]);
11645 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11647 // convert vertex positions to texcoords
11648 Matrix4x4_Transform(projection, v[cornerindex], temp);
11649 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11650 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11651 // calculate distance fade from the projection origin
11652 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11653 f = bound(0.0f, f, 1.0f);
11654 c[cornerindex][0] = r * f;
11655 c[cornerindex][1] = g * f;
11656 c[cornerindex][2] = b * f;
11657 c[cornerindex][3] = 1.0f;
11658 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11661 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);
11663 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11664 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);
11666 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)
11668 matrix4x4_t projection;
11669 decalsystem_t *decalsystem;
11672 const msurface_t *surface;
11673 const msurface_t *surfaces;
11674 const int *surfacelist;
11675 const texture_t *texture;
11677 int numsurfacelist;
11678 int surfacelistindex;
11681 float localorigin[3];
11682 float localnormal[3];
11683 float localmins[3];
11684 float localmaxs[3];
11687 float planes[6][4];
11690 int bih_triangles_count;
11691 int bih_triangles[256];
11692 int bih_surfaces[256];
11694 decalsystem = &ent->decalsystem;
11695 model = ent->model;
11696 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11698 R_DecalSystem_Reset(&ent->decalsystem);
11702 if (!model->brush.data_leafs && !cl_decals_models.integer)
11704 if (decalsystem->model)
11705 R_DecalSystem_Reset(decalsystem);
11709 if (decalsystem->model != model)
11710 R_DecalSystem_Reset(decalsystem);
11711 decalsystem->model = model;
11713 RSurf_ActiveModelEntity(ent, true, false, false);
11715 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11716 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11717 VectorNormalize(localnormal);
11718 localsize = worldsize*rsurface.inversematrixscale;
11719 localmins[0] = localorigin[0] - localsize;
11720 localmins[1] = localorigin[1] - localsize;
11721 localmins[2] = localorigin[2] - localsize;
11722 localmaxs[0] = localorigin[0] + localsize;
11723 localmaxs[1] = localorigin[1] + localsize;
11724 localmaxs[2] = localorigin[2] + localsize;
11726 //VectorCopy(localnormal, planes[4]);
11727 //VectorVectors(planes[4], planes[2], planes[0]);
11728 AnglesFromVectors(angles, localnormal, NULL, false);
11729 AngleVectors(angles, planes[0], planes[2], planes[4]);
11730 VectorNegate(planes[0], planes[1]);
11731 VectorNegate(planes[2], planes[3]);
11732 VectorNegate(planes[4], planes[5]);
11733 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11734 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11735 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11736 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11737 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11738 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11743 matrix4x4_t forwardprojection;
11744 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11745 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11750 float projectionvector[4][3];
11751 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11752 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11753 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11754 projectionvector[0][0] = planes[0][0] * ilocalsize;
11755 projectionvector[0][1] = planes[1][0] * ilocalsize;
11756 projectionvector[0][2] = planes[2][0] * ilocalsize;
11757 projectionvector[1][0] = planes[0][1] * ilocalsize;
11758 projectionvector[1][1] = planes[1][1] * ilocalsize;
11759 projectionvector[1][2] = planes[2][1] * ilocalsize;
11760 projectionvector[2][0] = planes[0][2] * ilocalsize;
11761 projectionvector[2][1] = planes[1][2] * ilocalsize;
11762 projectionvector[2][2] = planes[2][2] * ilocalsize;
11763 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11764 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11765 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11766 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11770 dynamic = model->surfmesh.isanimated;
11771 numsurfacelist = model->nummodelsurfaces;
11772 surfacelist = model->sortedmodelsurfaces;
11773 surfaces = model->data_surfaces;
11776 bih_triangles_count = -1;
11779 if(model->render_bih.numleafs)
11780 bih = &model->render_bih;
11781 else if(model->collision_bih.numleafs)
11782 bih = &model->collision_bih;
11785 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11786 if(bih_triangles_count == 0)
11788 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11790 if(bih_triangles_count > 0)
11792 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11794 surfaceindex = bih_surfaces[triangleindex];
11795 surface = surfaces + surfaceindex;
11796 texture = surface->texture;
11797 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11799 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11801 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11806 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11808 surfaceindex = surfacelist[surfacelistindex];
11809 surface = surfaces + surfaceindex;
11810 // check cull box first because it rejects more than any other check
11811 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11813 // skip transparent surfaces
11814 texture = surface->texture;
11815 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11817 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11819 numtriangles = surface->num_triangles;
11820 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11821 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11826 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11827 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)
11829 int renderentityindex;
11830 float worldmins[3];
11831 float worldmaxs[3];
11832 entity_render_t *ent;
11834 if (!cl_decals_newsystem.integer)
11837 worldmins[0] = worldorigin[0] - worldsize;
11838 worldmins[1] = worldorigin[1] - worldsize;
11839 worldmins[2] = worldorigin[2] - worldsize;
11840 worldmaxs[0] = worldorigin[0] + worldsize;
11841 worldmaxs[1] = worldorigin[1] + worldsize;
11842 worldmaxs[2] = worldorigin[2] + worldsize;
11844 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11846 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11848 ent = r_refdef.scene.entities[renderentityindex];
11849 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11852 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11856 typedef struct r_decalsystem_splatqueue_s
11858 vec3_t worldorigin;
11859 vec3_t worldnormal;
11863 unsigned int decalsequence;
11865 r_decalsystem_splatqueue_t;
11867 int r_decalsystem_numqueued = 0;
11868 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11870 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)
11872 r_decalsystem_splatqueue_t *queue;
11874 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11877 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11878 VectorCopy(worldorigin, queue->worldorigin);
11879 VectorCopy(worldnormal, queue->worldnormal);
11880 Vector4Set(queue->color, r, g, b, a);
11881 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11882 queue->worldsize = worldsize;
11883 queue->decalsequence = cl.decalsequence++;
11886 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11889 r_decalsystem_splatqueue_t *queue;
11891 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11892 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);
11893 r_decalsystem_numqueued = 0;
11896 extern cvar_t cl_decals_max;
11897 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11900 decalsystem_t *decalsystem = &ent->decalsystem;
11902 unsigned int killsequence;
11907 if (!decalsystem->numdecals)
11910 if (r_showsurfaces.integer)
11913 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11915 R_DecalSystem_Reset(decalsystem);
11919 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11920 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11922 if (decalsystem->lastupdatetime)
11923 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11926 decalsystem->lastupdatetime = r_refdef.scene.time;
11927 numdecals = decalsystem->numdecals;
11929 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11931 if (decal->color4f[0][3])
11933 decal->lived += frametime;
11934 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11936 memset(decal, 0, sizeof(*decal));
11937 if (decalsystem->freedecal > i)
11938 decalsystem->freedecal = i;
11942 decal = decalsystem->decals;
11943 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11946 // collapse the array by shuffling the tail decals into the gaps
11949 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11950 decalsystem->freedecal++;
11951 if (decalsystem->freedecal == numdecals)
11953 decal[decalsystem->freedecal] = decal[--numdecals];
11956 decalsystem->numdecals = numdecals;
11958 if (numdecals <= 0)
11960 // if there are no decals left, reset decalsystem
11961 R_DecalSystem_Reset(decalsystem);
11965 extern skinframe_t *decalskinframe;
11966 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11969 decalsystem_t *decalsystem = &ent->decalsystem;
11978 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11981 numdecals = decalsystem->numdecals;
11985 if (r_showsurfaces.integer)
11988 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11990 R_DecalSystem_Reset(decalsystem);
11994 // if the model is static it doesn't matter what value we give for
11995 // wantnormals and wanttangents, so this logic uses only rules applicable
11996 // to a model, knowing that they are meaningless otherwise
11997 RSurf_ActiveModelEntity(ent, false, false, false);
11999 decalsystem->lastupdatetime = r_refdef.scene.time;
12001 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12003 // update vertex positions for animated models
12004 v3f = decalsystem->vertex3f;
12005 c4f = decalsystem->color4f;
12006 t2f = decalsystem->texcoord2f;
12007 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12009 if (!decal->color4f[0][3])
12012 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12016 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12019 // update color values for fading decals
12020 if (decal->lived >= cl_decals_time.value)
12021 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12025 c4f[ 0] = decal->color4f[0][0] * alpha;
12026 c4f[ 1] = decal->color4f[0][1] * alpha;
12027 c4f[ 2] = decal->color4f[0][2] * alpha;
12029 c4f[ 4] = decal->color4f[1][0] * alpha;
12030 c4f[ 5] = decal->color4f[1][1] * alpha;
12031 c4f[ 6] = decal->color4f[1][2] * alpha;
12033 c4f[ 8] = decal->color4f[2][0] * alpha;
12034 c4f[ 9] = decal->color4f[2][1] * alpha;
12035 c4f[10] = decal->color4f[2][2] * alpha;
12038 t2f[0] = decal->texcoord2f[0][0];
12039 t2f[1] = decal->texcoord2f[0][1];
12040 t2f[2] = decal->texcoord2f[1][0];
12041 t2f[3] = decal->texcoord2f[1][1];
12042 t2f[4] = decal->texcoord2f[2][0];
12043 t2f[5] = decal->texcoord2f[2][1];
12045 // update vertex positions for animated models
12046 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12048 e = rsurface.modelelement3i + 3*decal->triangleindex;
12049 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12050 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12051 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12055 VectorCopy(decal->vertex3f[0], v3f);
12056 VectorCopy(decal->vertex3f[1], v3f + 3);
12057 VectorCopy(decal->vertex3f[2], v3f + 6);
12060 if (r_refdef.fogenabled)
12062 alpha = RSurf_FogVertex(v3f);
12063 VectorScale(c4f, alpha, c4f);
12064 alpha = RSurf_FogVertex(v3f + 3);
12065 VectorScale(c4f + 4, alpha, c4f + 4);
12066 alpha = RSurf_FogVertex(v3f + 6);
12067 VectorScale(c4f + 8, alpha, c4f + 8);
12078 r_refdef.stats[r_stat_drawndecals] += numtris;
12080 // now render the decals all at once
12081 // (this assumes they all use one particle font texture!)
12082 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);
12083 // R_Mesh_ResetTextureState();
12084 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12085 GL_DepthMask(false);
12086 GL_DepthRange(0, 1);
12087 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12088 GL_DepthTest(true);
12089 GL_CullFace(GL_NONE);
12090 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12091 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12092 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12096 static void R_DrawModelDecals(void)
12100 // fade faster when there are too many decals
12101 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12102 for (i = 0;i < r_refdef.scene.numentities;i++)
12103 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12105 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12106 for (i = 0;i < r_refdef.scene.numentities;i++)
12107 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12108 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12110 R_DecalSystem_ApplySplatEntitiesQueue();
12112 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12113 for (i = 0;i < r_refdef.scene.numentities;i++)
12114 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12116 r_refdef.stats[r_stat_totaldecals] += numdecals;
12118 if (r_showsurfaces.integer)
12121 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12123 for (i = 0;i < r_refdef.scene.numentities;i++)
12125 if (!r_refdef.viewcache.entityvisible[i])
12127 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12128 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12132 extern cvar_t mod_collision_bih;
12133 static void R_DrawDebugModel(void)
12135 entity_render_t *ent = rsurface.entity;
12136 int i, j, flagsmask;
12137 const msurface_t *surface;
12138 dp_model_t *model = ent->model;
12140 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12143 if (r_showoverdraw.value > 0)
12145 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12146 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12147 R_SetupShader_Generic_NoTexture(false, false);
12148 GL_DepthTest(false);
12149 GL_DepthMask(false);
12150 GL_DepthRange(0, 1);
12151 GL_BlendFunc(GL_ONE, GL_ONE);
12152 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12154 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12156 rsurface.texture = R_GetCurrentTexture(surface->texture);
12157 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12159 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12160 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12161 if (!rsurface.texture->currentlayers->depthmask)
12162 GL_Color(c, 0, 0, 1.0f);
12163 else if (ent == r_refdef.scene.worldentity)
12164 GL_Color(c, c, c, 1.0f);
12166 GL_Color(0, c, 0, 1.0f);
12167 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12171 rsurface.texture = NULL;
12174 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12176 // R_Mesh_ResetTextureState();
12177 R_SetupShader_Generic_NoTexture(false, false);
12178 GL_DepthRange(0, 1);
12179 GL_DepthTest(!r_showdisabledepthtest.integer);
12180 GL_DepthMask(false);
12181 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12183 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12187 qboolean cullbox = false;
12188 const q3mbrush_t *brush;
12189 const bih_t *bih = &model->collision_bih;
12190 const bih_leaf_t *bihleaf;
12191 float vertex3f[3][3];
12192 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12193 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12195 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12197 switch (bihleaf->type)
12200 brush = model->brush.data_brushes + bihleaf->itemindex;
12201 if (brush->colbrushf && brush->colbrushf->numtriangles)
12203 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);
12204 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12205 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12208 case BIH_COLLISIONTRIANGLE:
12209 triangleindex = bihleaf->itemindex;
12210 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12211 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12212 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12213 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);
12214 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12215 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12217 case BIH_RENDERTRIANGLE:
12218 triangleindex = bihleaf->itemindex;
12219 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12220 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12221 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12222 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);
12223 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12224 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12230 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12233 if (r_showtris.integer && qglPolygonMode)
12235 if (r_showdisabledepthtest.integer)
12237 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12238 GL_DepthMask(false);
12242 GL_BlendFunc(GL_ONE, GL_ZERO);
12243 GL_DepthMask(true);
12245 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12246 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12248 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12250 rsurface.texture = R_GetCurrentTexture(surface->texture);
12251 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12253 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12254 if (!rsurface.texture->currentlayers->depthmask)
12255 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12256 else if (ent == r_refdef.scene.worldentity)
12257 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12259 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12260 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12264 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12265 rsurface.texture = NULL;
12268 if (r_shownormals.value != 0 && qglBegin)
12272 if (r_showdisabledepthtest.integer)
12274 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12275 GL_DepthMask(false);
12279 GL_BlendFunc(GL_ONE, GL_ZERO);
12280 GL_DepthMask(true);
12282 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12284 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12286 rsurface.texture = R_GetCurrentTexture(surface->texture);
12287 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12289 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12290 qglBegin(GL_LINES);
12291 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12293 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12295 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12296 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12297 qglVertex3f(v[0], v[1], v[2]);
12298 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12299 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12300 qglVertex3f(v[0], v[1], v[2]);
12303 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12305 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12307 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12308 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12309 qglVertex3f(v[0], v[1], v[2]);
12310 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12311 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12312 qglVertex3f(v[0], v[1], v[2]);
12315 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12317 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12319 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12320 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12321 qglVertex3f(v[0], v[1], v[2]);
12322 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12323 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12324 qglVertex3f(v[0], v[1], v[2]);
12327 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12329 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12331 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12332 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12333 qglVertex3f(v[0], v[1], v[2]);
12334 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12335 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12336 qglVertex3f(v[0], v[1], v[2]);
12343 rsurface.texture = NULL;
12348 int r_maxsurfacelist = 0;
12349 const msurface_t **r_surfacelist = NULL;
12350 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12352 int i, j, endj, flagsmask;
12353 dp_model_t *model = ent->model;
12354 msurface_t *surfaces;
12355 unsigned char *update;
12356 int numsurfacelist = 0;
12360 if (r_maxsurfacelist < model->num_surfaces)
12362 r_maxsurfacelist = model->num_surfaces;
12364 Mem_Free((msurface_t **)r_surfacelist);
12365 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12368 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12369 RSurf_ActiveModelEntity(ent, false, false, false);
12371 RSurf_ActiveModelEntity(ent, true, true, true);
12372 else if (depthonly)
12374 switch (vid.renderpath)
12376 case RENDERPATH_GL20:
12377 case RENDERPATH_D3D9:
12378 case RENDERPATH_D3D10:
12379 case RENDERPATH_D3D11:
12380 case RENDERPATH_SOFT:
12381 case RENDERPATH_GLES2:
12382 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12384 case RENDERPATH_GL11:
12385 case RENDERPATH_GL13:
12386 case RENDERPATH_GLES1:
12387 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12393 switch (vid.renderpath)
12395 case RENDERPATH_GL20:
12396 case RENDERPATH_D3D9:
12397 case RENDERPATH_D3D10:
12398 case RENDERPATH_D3D11:
12399 case RENDERPATH_SOFT:
12400 case RENDERPATH_GLES2:
12401 RSurf_ActiveModelEntity(ent, true, true, false);
12403 case RENDERPATH_GL11:
12404 case RENDERPATH_GL13:
12405 case RENDERPATH_GLES1:
12406 RSurf_ActiveModelEntity(ent, true, false, false);
12411 surfaces = model->data_surfaces;
12412 update = model->brushq1.lightmapupdateflags;
12414 // update light styles
12415 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12417 model_brush_lightstyleinfo_t *style;
12418 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12420 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12422 int *list = style->surfacelist;
12423 style->value = r_refdef.scene.lightstylevalue[style->style];
12424 for (j = 0;j < style->numsurfaces;j++)
12425 update[list[j]] = true;
12430 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12434 R_DrawDebugModel();
12435 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12439 rsurface.lightmaptexture = NULL;
12440 rsurface.deluxemaptexture = NULL;
12441 rsurface.uselightmaptexture = false;
12442 rsurface.texture = NULL;
12443 rsurface.rtlight = NULL;
12444 numsurfacelist = 0;
12445 // add visible surfaces to draw list
12446 if (ent == r_refdef.scene.worldentity)
12448 // for the world entity, check surfacevisible
12449 for (i = 0;i < model->nummodelsurfaces;i++)
12451 j = model->sortedmodelsurfaces[i];
12452 if (r_refdef.viewcache.world_surfacevisible[j])
12453 r_surfacelist[numsurfacelist++] = surfaces + j;
12458 // add all surfaces
12459 for (i = 0; i < model->nummodelsurfaces; i++)
12460 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12462 // don't do anything if there were no surfaces
12463 if (!numsurfacelist)
12465 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12468 // update lightmaps if needed
12472 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12477 R_BuildLightMap(ent, surfaces + j);
12482 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12484 // add to stats if desired
12485 if (r_speeds.integer && !skysurfaces && !depthonly)
12487 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12488 for (j = 0;j < numsurfacelist;j++)
12489 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12492 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12495 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12498 static texture_t texture;
12499 static msurface_t surface;
12500 const msurface_t *surfacelist = &surface;
12502 // fake enough texture and surface state to render this geometry
12504 texture.update_lastrenderframe = -1; // regenerate this texture
12505 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12506 texture.basealpha = 1.0f;
12507 texture.currentskinframe = skinframe;
12508 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12509 texture.offsetmapping = OFFSETMAPPING_OFF;
12510 texture.offsetscale = 1;
12511 texture.specularscalemod = 1;
12512 texture.specularpowermod = 1;
12513 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12514 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12515 // JUST GREP FOR "specularscalemod = 1".
12517 for (q = 0; q < 3; q++)
12519 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12520 texture.render_modellight_lightdir[q] = q == 2;
12521 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12522 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12523 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12524 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12525 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12526 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12527 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12528 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12530 texture.currentalpha = 1.0f;
12532 surface.texture = &texture;
12533 surface.num_triangles = numtriangles;
12534 surface.num_firsttriangle = firsttriangle;
12535 surface.num_vertices = numvertices;
12536 surface.num_firstvertex = firstvertex;
12539 rsurface.texture = R_GetCurrentTexture(surface.texture);
12540 rsurface.lightmaptexture = NULL;
12541 rsurface.deluxemaptexture = NULL;
12542 rsurface.uselightmaptexture = false;
12543 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12546 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)
12548 static msurface_t surface;
12549 const msurface_t *surfacelist = &surface;
12551 // fake enough texture and surface state to render this geometry
12552 surface.texture = texture;
12553 surface.num_triangles = numtriangles;
12554 surface.num_firsttriangle = firsttriangle;
12555 surface.num_vertices = numvertices;
12556 surface.num_firstvertex = firstvertex;
12559 rsurface.texture = R_GetCurrentTexture(surface.texture);
12560 rsurface.lightmaptexture = NULL;
12561 rsurface.deluxemaptexture = NULL;
12562 rsurface.uselightmaptexture = false;
12563 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);