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");
7442 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7444 if (r_refdef.view.showdebug)
7446 if (cl_locs_show.integer)
7449 if (r_timereport_active)
7450 R_TimeReport("showlocs");
7453 if (r_drawportals.integer)
7456 if (r_timereport_active)
7457 R_TimeReport("portals");
7460 if (r_showbboxes_client.value > 0)
7462 R_DrawEntityBBoxes(CLVM_prog);
7463 if (r_timereport_active)
7464 R_TimeReport("clbboxes");
7466 if (r_showbboxes.value > 0)
7468 R_DrawEntityBBoxes(SVVM_prog);
7469 if (r_timereport_active)
7470 R_TimeReport("svbboxes");
7474 if (r_transparent.integer)
7476 R_MeshQueue_RenderTransparent();
7477 if (r_timereport_active)
7478 R_TimeReport("drawtrans");
7481 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))
7483 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7484 if (r_timereport_active)
7485 R_TimeReport("worlddebug");
7486 R_DrawModelsDebug();
7487 if (r_timereport_active)
7488 R_TimeReport("modeldebug");
7491 if (cl.csqc_vidvars.drawworld)
7493 R_Shadow_DrawCoronas();
7494 if (r_timereport_active)
7495 R_TimeReport("coronas");
7500 GL_DepthTest(false);
7501 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7502 GL_Color(1, 1, 1, 1);
7503 qglBegin(GL_POLYGON);
7504 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7505 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7506 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7507 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7509 qglBegin(GL_POLYGON);
7510 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]);
7511 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]);
7512 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]);
7513 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]);
7515 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7519 // don't let sound skip if going slow
7520 if (r_refdef.scene.extraupdate)
7524 static const unsigned short bboxelements[36] =
7534 #define BBOXEDGES 13
7535 static const float bboxedges[BBOXEDGES][6] =
7538 { 0, 0, 0, 1, 1, 1 },
7540 { 0, 0, 0, 0, 1, 0 },
7541 { 0, 0, 0, 1, 0, 0 },
7542 { 0, 1, 0, 1, 1, 0 },
7543 { 1, 0, 0, 1, 1, 0 },
7545 { 0, 0, 1, 0, 1, 1 },
7546 { 0, 0, 1, 1, 0, 1 },
7547 { 0, 1, 1, 1, 1, 1 },
7548 { 1, 0, 1, 1, 1, 1 },
7550 { 0, 0, 0, 0, 0, 1 },
7551 { 1, 0, 0, 1, 0, 1 },
7552 { 0, 1, 0, 0, 1, 1 },
7553 { 1, 1, 0, 1, 1, 1 },
7556 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7558 int numvertices = BBOXEDGES * 8;
7559 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7560 int numtriangles = BBOXEDGES * 12;
7561 unsigned short elements[BBOXEDGES * 36];
7563 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7565 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7567 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7568 GL_DepthMask(false);
7569 GL_DepthRange(0, 1);
7570 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7572 for (edge = 0; edge < BBOXEDGES; edge++)
7574 for (i = 0; i < 3; i++)
7576 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7577 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7579 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7580 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7581 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7582 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7583 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7584 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7585 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7586 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7587 for (i = 0; i < 36; i++)
7588 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7590 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7591 if (r_refdef.fogenabled)
7593 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7595 f1 = RSurf_FogVertex(v);
7597 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7598 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7599 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7602 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7603 R_Mesh_ResetTextureState();
7604 R_SetupShader_Generic_NoTexture(false, false);
7605 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7608 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7610 // hacky overloading of the parameters
7611 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7614 prvm_edict_t *edict;
7616 GL_CullFace(GL_NONE);
7617 R_SetupShader_Generic_NoTexture(false, false);
7619 for (i = 0;i < numsurfaces;i++)
7621 edict = PRVM_EDICT_NUM(surfacelist[i]);
7622 switch ((int)PRVM_serveredictfloat(edict, solid))
7624 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7625 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7626 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7627 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7628 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7629 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7630 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7632 if (prog == CLVM_prog)
7633 color[3] *= r_showbboxes_client.value;
7635 color[3] *= r_showbboxes.value;
7636 color[3] = bound(0, color[3], 1);
7637 GL_DepthTest(!r_showdisabledepthtest.integer);
7638 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7642 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7645 prvm_edict_t *edict;
7651 for (i = 0; i < prog->num_edicts; i++)
7653 edict = PRVM_EDICT_NUM(i);
7654 if (edict->priv.server->free)
7656 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7657 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7659 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7661 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7662 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7666 static const int nomodelelement3i[24] =
7678 static const unsigned short nomodelelement3s[24] =
7690 static const float nomodelvertex3f[6*3] =
7700 static const float nomodelcolor4f[6*4] =
7702 0.0f, 0.0f, 0.5f, 1.0f,
7703 0.0f, 0.0f, 0.5f, 1.0f,
7704 0.0f, 0.5f, 0.0f, 1.0f,
7705 0.0f, 0.5f, 0.0f, 1.0f,
7706 0.5f, 0.0f, 0.0f, 1.0f,
7707 0.5f, 0.0f, 0.0f, 1.0f
7710 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7716 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);
7718 // this is only called once per entity so numsurfaces is always 1, and
7719 // surfacelist is always {0}, so this code does not handle batches
7721 if (rsurface.ent_flags & RENDER_ADDITIVE)
7723 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7724 GL_DepthMask(false);
7726 else if (ent->alpha < 1)
7728 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7729 GL_DepthMask(false);
7733 GL_BlendFunc(GL_ONE, GL_ZERO);
7736 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7737 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7738 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7739 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7740 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7741 for (i = 0, c = color4f;i < 6;i++, c += 4)
7743 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7744 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7745 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7748 if (r_refdef.fogenabled)
7750 for (i = 0, c = color4f;i < 6;i++, c += 4)
7752 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7754 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7755 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7756 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7759 // R_Mesh_ResetTextureState();
7760 R_SetupShader_Generic_NoTexture(false, false);
7761 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7762 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7765 void R_DrawNoModel(entity_render_t *ent)
7768 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7769 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7770 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7772 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7775 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7777 vec3_t right1, right2, diff, normal;
7779 VectorSubtract (org2, org1, normal);
7781 // calculate 'right' vector for start
7782 VectorSubtract (r_refdef.view.origin, org1, diff);
7783 CrossProduct (normal, diff, right1);
7784 VectorNormalize (right1);
7786 // calculate 'right' vector for end
7787 VectorSubtract (r_refdef.view.origin, org2, diff);
7788 CrossProduct (normal, diff, right2);
7789 VectorNormalize (right2);
7791 vert[ 0] = org1[0] + width * right1[0];
7792 vert[ 1] = org1[1] + width * right1[1];
7793 vert[ 2] = org1[2] + width * right1[2];
7794 vert[ 3] = org1[0] - width * right1[0];
7795 vert[ 4] = org1[1] - width * right1[1];
7796 vert[ 5] = org1[2] - width * right1[2];
7797 vert[ 6] = org2[0] - width * right2[0];
7798 vert[ 7] = org2[1] - width * right2[1];
7799 vert[ 8] = org2[2] - width * right2[2];
7800 vert[ 9] = org2[0] + width * right2[0];
7801 vert[10] = org2[1] + width * right2[1];
7802 vert[11] = org2[2] + width * right2[2];
7805 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)
7807 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7808 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7809 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7810 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7811 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7812 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7813 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7814 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7815 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7816 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7817 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7818 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7821 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7826 VectorSet(v, x, y, z);
7827 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7828 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7830 if (i == mesh->numvertices)
7832 if (mesh->numvertices < mesh->maxvertices)
7834 VectorCopy(v, vertex3f);
7835 mesh->numvertices++;
7837 return mesh->numvertices;
7843 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7847 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7848 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7849 e = mesh->element3i + mesh->numtriangles * 3;
7850 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7852 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7853 if (mesh->numtriangles < mesh->maxtriangles)
7858 mesh->numtriangles++;
7860 element[1] = element[2];
7864 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7868 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7869 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7870 e = mesh->element3i + mesh->numtriangles * 3;
7871 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7873 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7874 if (mesh->numtriangles < mesh->maxtriangles)
7879 mesh->numtriangles++;
7881 element[1] = element[2];
7885 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7886 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7888 int planenum, planenum2;
7891 mplane_t *plane, *plane2;
7893 double temppoints[2][256*3];
7894 // figure out how large a bounding box we need to properly compute this brush
7896 for (w = 0;w < numplanes;w++)
7897 maxdist = max(maxdist, fabs(planes[w].dist));
7898 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7899 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7900 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7904 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7905 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7907 if (planenum2 == planenum)
7909 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);
7912 if (tempnumpoints < 3)
7914 // generate elements forming a triangle fan for this polygon
7915 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7919 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)
7921 texturelayer_t *layer;
7922 layer = t->currentlayers + t->currentnumlayers++;
7924 layer->depthmask = depthmask;
7925 layer->blendfunc1 = blendfunc1;
7926 layer->blendfunc2 = blendfunc2;
7927 layer->texture = texture;
7928 layer->texmatrix = *matrix;
7929 layer->color[0] = r;
7930 layer->color[1] = g;
7931 layer->color[2] = b;
7932 layer->color[3] = a;
7935 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7937 if(parms[0] == 0 && parms[1] == 0)
7939 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7940 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7945 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7948 index = parms[2] + rsurface.shadertime * parms[3];
7949 index -= floor(index);
7950 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7953 case Q3WAVEFUNC_NONE:
7954 case Q3WAVEFUNC_NOISE:
7955 case Q3WAVEFUNC_COUNT:
7958 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7959 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7960 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7961 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7962 case Q3WAVEFUNC_TRIANGLE:
7964 f = index - floor(index);
7977 f = parms[0] + parms[1] * f;
7978 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7979 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7983 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7990 matrix4x4_t matrix, temp;
7991 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7992 // it's better to have one huge fixup every 9 hours than gradual
7993 // degradation over time which looks consistently bad after many hours.
7995 // tcmod scroll in particular suffers from this degradation which can't be
7996 // effectively worked around even with floor() tricks because we don't
7997 // know if tcmod scroll is the last tcmod being applied, and for clampmap
7998 // a workaround involving floor() would be incorrect anyway...
7999 shadertime = rsurface.shadertime;
8000 if (shadertime >= 32768.0f)
8001 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8002 switch(tcmod->tcmod)
8006 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8007 matrix = r_waterscrollmatrix;
8009 matrix = identitymatrix;
8011 case Q3TCMOD_ENTITYTRANSLATE:
8012 // this is used in Q3 to allow the gamecode to control texcoord
8013 // scrolling on the entity, which is not supported in darkplaces yet.
8014 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8016 case Q3TCMOD_ROTATE:
8017 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8018 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8019 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8022 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8024 case Q3TCMOD_SCROLL:
8025 // this particular tcmod is a "bug for bug" compatible one with regards to
8026 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8027 // specifically did the wrapping and so we must mimic that...
8028 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8029 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8030 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8032 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8033 w = (int) tcmod->parms[0];
8034 h = (int) tcmod->parms[1];
8035 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8037 idx = (int) floor(f * w * h);
8038 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8040 case Q3TCMOD_STRETCH:
8041 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8042 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8044 case Q3TCMOD_TRANSFORM:
8045 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8046 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8047 VectorSet(tcmat + 6, 0 , 0 , 1);
8048 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8049 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8051 case Q3TCMOD_TURBULENT:
8052 // this is handled in the RSurf_PrepareVertices function
8053 matrix = identitymatrix;
8057 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8060 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8062 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8063 char name[MAX_QPATH];
8064 skinframe_t *skinframe;
8065 unsigned char pixels[296*194];
8066 strlcpy(cache->name, skinname, sizeof(cache->name));
8067 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8068 if (developer_loading.integer)
8069 Con_Printf("loading %s\n", name);
8070 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8071 if (!skinframe || !skinframe->base)
8074 fs_offset_t filesize;
8076 f = FS_LoadFile(name, tempmempool, true, &filesize);
8079 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8080 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8084 cache->skinframe = skinframe;
8087 texture_t *R_GetCurrentTexture(texture_t *t)
8090 const entity_render_t *ent = rsurface.entity;
8091 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8092 q3shaderinfo_layer_tcmod_t *tcmod;
8093 float specularscale = 0.0f;
8095 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8096 return t->currentframe;
8097 t->update_lastrenderframe = r_textureframe;
8098 t->update_lastrenderentity = (void *)ent;
8100 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8101 t->camera_entity = ent->entitynumber;
8103 t->camera_entity = 0;
8105 // switch to an alternate material if this is a q1bsp animated material
8107 texture_t *texture = t;
8108 int s = rsurface.ent_skinnum;
8109 if ((unsigned int)s >= (unsigned int)model->numskins)
8111 if (model->skinscenes)
8113 if (model->skinscenes[s].framecount > 1)
8114 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8116 s = model->skinscenes[s].firstframe;
8119 t = t + s * model->num_surfaces;
8122 // use an alternate animation if the entity's frame is not 0,
8123 // and only if the texture has an alternate animation
8124 if (t->animated == 2) // q2bsp
8125 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8126 else if (rsurface.ent_alttextures && t->anim_total[1])
8127 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8129 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8131 texture->currentframe = t;
8134 // update currentskinframe to be a qw skin or animation frame
8135 if (rsurface.ent_qwskin >= 0)
8137 i = rsurface.ent_qwskin;
8138 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8140 r_qwskincache_size = cl.maxclients;
8142 Mem_Free(r_qwskincache);
8143 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8145 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8146 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8147 t->currentskinframe = r_qwskincache[i].skinframe;
8148 if (t->materialshaderpass && t->currentskinframe == NULL)
8149 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8151 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8152 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8153 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8154 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8156 t->currentmaterialflags = t->basematerialflags;
8157 t->currentalpha = rsurface.entity->alpha * t->basealpha;
8158 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8159 t->currentalpha *= r_wateralpha.value;
8160 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8161 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8162 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8163 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8165 // decide on which type of lighting to use for this surface
8166 if (rsurface.entity->render_modellight_forced)
8167 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8168 if (rsurface.entity->render_rtlight_disabled)
8169 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8170 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8172 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8173 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8174 for (q = 0; q < 3; q++)
8176 t->render_glowmod[q] = rsurface.entity->glowmod[q];
8177 t->render_modellight_lightdir[q] = q == 2;
8178 t->render_modellight_ambient[q] = 1;
8179 t->render_modellight_diffuse[q] = 0;
8180 t->render_modellight_specular[q] = 0;
8181 t->render_lightmap_ambient[q] = 0;
8182 t->render_lightmap_diffuse[q] = 0;
8183 t->render_lightmap_specular[q] = 0;
8184 t->render_rtlight_diffuse[q] = 0;
8185 t->render_rtlight_specular[q] = 0;
8188 else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8190 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8191 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8192 for (q = 0; q < 3; q++)
8194 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8195 t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8196 t->render_modellight_lightdir[q] = q == 2;
8197 t->render_modellight_diffuse[q] = 0;
8198 t->render_modellight_specular[q] = 0;
8199 t->render_lightmap_ambient[q] = 0;
8200 t->render_lightmap_diffuse[q] = 0;
8201 t->render_lightmap_specular[q] = 0;
8202 t->render_rtlight_diffuse[q] = 0;
8203 t->render_rtlight_specular[q] = 0;
8206 else if (FAKELIGHT_ENABLED)
8208 // no modellight if using fakelight for the map
8209 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8210 for (q = 0; q < 3; q++)
8212 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8213 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8214 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8215 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8216 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8217 t->render_lightmap_ambient[q] = 0;
8218 t->render_lightmap_diffuse[q] = 0;
8219 t->render_lightmap_specular[q] = 0;
8220 t->render_rtlight_diffuse[q] = 0;
8221 t->render_rtlight_specular[q] = 0;
8224 else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8226 // ambient + single direction light (modellight)
8227 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8228 for (q = 0; q < 3; q++)
8230 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8231 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8232 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8233 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8234 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8235 t->render_lightmap_ambient[q] = 0;
8236 t->render_lightmap_diffuse[q] = 0;
8237 t->render_lightmap_specular[q] = 0;
8238 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8239 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8244 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8245 for (q = 0; q < 3; q++)
8247 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8248 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8249 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8250 t->render_modellight_diffuse[q] = 0;
8251 t->render_modellight_specular[q] = 0;
8252 t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8253 t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8254 t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8255 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8256 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8260 for (q = 0; q < 3; q++)
8262 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8263 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8266 if (rsurface.ent_flags & RENDER_ADDITIVE)
8267 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8268 else if (t->currentalpha < 1)
8269 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8270 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8271 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8272 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8273 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8274 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8275 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8276 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8277 if (t->backgroundshaderpass)
8278 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8279 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8281 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8282 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8285 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8286 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8288 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8289 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8291 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8292 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8294 // there is no tcmod
8295 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8297 t->currenttexmatrix = r_waterscrollmatrix;
8298 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8300 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8302 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8303 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8306 if (t->materialshaderpass)
8307 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8308 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8310 t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8311 if (t->currentskinframe->qpixels)
8312 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8313 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8314 if (!t->basetexture)
8315 t->basetexture = r_texture_notexture;
8316 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8317 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8318 t->nmaptexture = t->currentskinframe->nmap;
8319 if (!t->nmaptexture)
8320 t->nmaptexture = r_texture_blanknormalmap;
8321 t->glosstexture = r_texture_black;
8322 t->glowtexture = t->currentskinframe->glow;
8323 t->fogtexture = t->currentskinframe->fog;
8324 t->reflectmasktexture = t->currentskinframe->reflect;
8325 if (t->backgroundshaderpass)
8327 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8328 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8329 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8330 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8331 t->backgroundglosstexture = r_texture_black;
8332 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8333 if (!t->backgroundnmaptexture)
8334 t->backgroundnmaptexture = r_texture_blanknormalmap;
8335 // make sure that if glow is going to be used, both textures are not NULL
8336 if (!t->backgroundglowtexture && t->glowtexture)
8337 t->backgroundglowtexture = r_texture_black;
8338 if (!t->glowtexture && t->backgroundglowtexture)
8339 t->glowtexture = r_texture_black;
8343 t->backgroundbasetexture = r_texture_white;
8344 t->backgroundnmaptexture = r_texture_blanknormalmap;
8345 t->backgroundglosstexture = r_texture_black;
8346 t->backgroundglowtexture = NULL;
8348 t->specularpower = r_shadow_glossexponent.value;
8349 // TODO: store reference values for these in the texture?
8350 if (r_shadow_gloss.integer > 0)
8352 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8354 if (r_shadow_glossintensity.value > 0)
8356 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8357 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8358 specularscale = r_shadow_glossintensity.value;
8361 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8363 t->glosstexture = r_texture_white;
8364 t->backgroundglosstexture = r_texture_white;
8365 specularscale = r_shadow_gloss2intensity.value;
8366 t->specularpower = r_shadow_gloss2exponent.value;
8369 specularscale *= t->specularscalemod;
8370 t->specularpower *= t->specularpowermod;
8372 // lightmaps mode looks bad with dlights using actual texturing, so turn
8373 // off the colormap and glossmap, but leave the normalmap on as it still
8374 // accurately represents the shading involved
8375 if (gl_lightmaps.integer)
8377 t->basetexture = r_texture_grey128;
8378 t->pantstexture = r_texture_black;
8379 t->shirttexture = r_texture_black;
8380 if (gl_lightmaps.integer < 2)
8381 t->nmaptexture = r_texture_blanknormalmap;
8382 t->glosstexture = r_texture_black;
8383 t->glowtexture = NULL;
8384 t->fogtexture = NULL;
8385 t->reflectmasktexture = NULL;
8386 t->backgroundbasetexture = NULL;
8387 if (gl_lightmaps.integer < 2)
8388 t->backgroundnmaptexture = r_texture_blanknormalmap;
8389 t->backgroundglosstexture = r_texture_black;
8390 t->backgroundglowtexture = NULL;
8392 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8395 if (specularscale != 1.0f)
8397 for (q = 0; q < 3; q++)
8399 t->render_modellight_specular[q] *= specularscale;
8400 t->render_lightmap_specular[q] *= specularscale;
8401 t->render_rtlight_specular[q] *= specularscale;
8405 t->currentnumlayers = 0;
8406 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8408 int blendfunc1, blendfunc2;
8410 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8412 blendfunc1 = GL_SRC_ALPHA;
8413 blendfunc2 = GL_ONE;
8415 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8417 blendfunc1 = GL_SRC_ALPHA;
8418 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8420 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8422 blendfunc1 = t->customblendfunc[0];
8423 blendfunc2 = t->customblendfunc[1];
8427 blendfunc1 = GL_ONE;
8428 blendfunc2 = GL_ZERO;
8430 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8431 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8433 // basic lit geometry
8434 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);
8435 // add pants/shirt if needed
8436 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8437 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);
8438 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8439 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);
8443 // basic lit geometry
8444 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);
8445 // add pants/shirt if needed
8446 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8447 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);
8448 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8449 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);
8450 // now add ambient passes if needed
8451 if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8453 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);
8454 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8455 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);
8456 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8457 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);
8460 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8461 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);
8462 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8464 // if this is opaque use alpha blend which will darken the earlier
8467 // if this is an alpha blended material, all the earlier passes
8468 // were darkened by fog already, so we only need to add the fog
8469 // color ontop through the fog mask texture
8471 // if this is an additive blended material, all the earlier passes
8472 // were darkened by fog already, and we should not add fog color
8473 // (because the background was not darkened, there is no fog color
8474 // that was lost behind it).
8475 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);
8482 rsurfacestate_t rsurface;
8484 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8486 dp_model_t *model = ent->model;
8487 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8489 rsurface.entity = (entity_render_t *)ent;
8490 rsurface.skeleton = ent->skeleton;
8491 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8492 rsurface.ent_skinnum = ent->skinnum;
8493 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;
8494 rsurface.ent_flags = ent->flags;
8495 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8496 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8497 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8498 rsurface.matrix = ent->matrix;
8499 rsurface.inversematrix = ent->inversematrix;
8500 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8501 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8502 R_EntityMatrix(&rsurface.matrix);
8503 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8504 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8505 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8506 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8507 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8508 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8509 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8510 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8511 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8512 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8513 if (ent->model->brush.submodel && !prepass)
8515 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8516 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8518 // if the animcache code decided it should use the shader path, skip the deform step
8519 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8520 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8521 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8522 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8523 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8524 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8526 if (ent->animcache_vertex3f)
8528 r_refdef.stats[r_stat_batch_entitycache_count]++;
8529 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8530 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8531 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8532 rsurface.modelvertex3f = ent->animcache_vertex3f;
8533 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8534 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8535 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8536 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8537 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8538 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8539 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8540 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8541 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8542 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8543 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8544 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8545 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8546 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8548 else if (wanttangents)
8550 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8551 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8552 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8553 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8554 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8555 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8556 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8557 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8558 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8559 rsurface.modelvertexmesh = NULL;
8560 rsurface.modelvertexmesh_vertexbuffer = NULL;
8561 rsurface.modelvertexmesh_bufferoffset = 0;
8562 rsurface.modelvertex3f_vertexbuffer = NULL;
8563 rsurface.modelvertex3f_bufferoffset = 0;
8564 rsurface.modelvertex3f_vertexbuffer = 0;
8565 rsurface.modelvertex3f_bufferoffset = 0;
8566 rsurface.modelsvector3f_vertexbuffer = 0;
8567 rsurface.modelsvector3f_bufferoffset = 0;
8568 rsurface.modeltvector3f_vertexbuffer = 0;
8569 rsurface.modeltvector3f_bufferoffset = 0;
8570 rsurface.modelnormal3f_vertexbuffer = 0;
8571 rsurface.modelnormal3f_bufferoffset = 0;
8573 else if (wantnormals)
8575 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8576 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8577 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8578 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8579 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8580 rsurface.modelsvector3f = NULL;
8581 rsurface.modeltvector3f = NULL;
8582 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8583 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8584 rsurface.modelvertexmesh = NULL;
8585 rsurface.modelvertexmesh_vertexbuffer = NULL;
8586 rsurface.modelvertexmesh_bufferoffset = 0;
8587 rsurface.modelvertex3f_vertexbuffer = NULL;
8588 rsurface.modelvertex3f_bufferoffset = 0;
8589 rsurface.modelvertex3f_vertexbuffer = 0;
8590 rsurface.modelvertex3f_bufferoffset = 0;
8591 rsurface.modelsvector3f_vertexbuffer = 0;
8592 rsurface.modelsvector3f_bufferoffset = 0;
8593 rsurface.modeltvector3f_vertexbuffer = 0;
8594 rsurface.modeltvector3f_bufferoffset = 0;
8595 rsurface.modelnormal3f_vertexbuffer = 0;
8596 rsurface.modelnormal3f_bufferoffset = 0;
8600 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8601 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8602 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8603 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8604 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8605 rsurface.modelsvector3f = NULL;
8606 rsurface.modeltvector3f = NULL;
8607 rsurface.modelnormal3f = NULL;
8608 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8609 rsurface.modelvertexmesh = NULL;
8610 rsurface.modelvertexmesh_vertexbuffer = NULL;
8611 rsurface.modelvertexmesh_bufferoffset = 0;
8612 rsurface.modelvertex3f_vertexbuffer = NULL;
8613 rsurface.modelvertex3f_bufferoffset = 0;
8614 rsurface.modelvertex3f_vertexbuffer = 0;
8615 rsurface.modelvertex3f_bufferoffset = 0;
8616 rsurface.modelsvector3f_vertexbuffer = 0;
8617 rsurface.modelsvector3f_bufferoffset = 0;
8618 rsurface.modeltvector3f_vertexbuffer = 0;
8619 rsurface.modeltvector3f_bufferoffset = 0;
8620 rsurface.modelnormal3f_vertexbuffer = 0;
8621 rsurface.modelnormal3f_bufferoffset = 0;
8623 rsurface.modelgeneratedvertex = true;
8627 if (rsurface.entityskeletaltransform3x4)
8629 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8630 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8631 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8632 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8636 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8637 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8638 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8639 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8641 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8642 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8643 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8644 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8645 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8646 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8647 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8648 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8649 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8650 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8651 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8652 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8653 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8654 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8655 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8656 rsurface.modelgeneratedvertex = false;
8658 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8659 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8660 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8661 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8662 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8663 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8664 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8665 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8666 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8667 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8668 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8669 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8670 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8671 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8672 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8673 rsurface.modelelement3i = model->surfmesh.data_element3i;
8674 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8675 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8676 rsurface.modelelement3s = model->surfmesh.data_element3s;
8677 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8678 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8679 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8680 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8681 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8682 rsurface.modelsurfaces = model->data_surfaces;
8683 rsurface.batchgeneratedvertex = false;
8684 rsurface.batchfirstvertex = 0;
8685 rsurface.batchnumvertices = 0;
8686 rsurface.batchfirsttriangle = 0;
8687 rsurface.batchnumtriangles = 0;
8688 rsurface.batchvertex3f = NULL;
8689 rsurface.batchvertex3f_vertexbuffer = NULL;
8690 rsurface.batchvertex3f_bufferoffset = 0;
8691 rsurface.batchsvector3f = NULL;
8692 rsurface.batchsvector3f_vertexbuffer = NULL;
8693 rsurface.batchsvector3f_bufferoffset = 0;
8694 rsurface.batchtvector3f = NULL;
8695 rsurface.batchtvector3f_vertexbuffer = NULL;
8696 rsurface.batchtvector3f_bufferoffset = 0;
8697 rsurface.batchnormal3f = NULL;
8698 rsurface.batchnormal3f_vertexbuffer = NULL;
8699 rsurface.batchnormal3f_bufferoffset = 0;
8700 rsurface.batchlightmapcolor4f = NULL;
8701 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8702 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8703 rsurface.batchtexcoordtexture2f = NULL;
8704 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8705 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8706 rsurface.batchtexcoordlightmap2f = NULL;
8707 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8708 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8709 rsurface.batchskeletalindex4ub = NULL;
8710 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8711 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8712 rsurface.batchskeletalweight4ub = NULL;
8713 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8714 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8715 rsurface.batchvertexmesh = NULL;
8716 rsurface.batchvertexmesh_vertexbuffer = NULL;
8717 rsurface.batchvertexmesh_bufferoffset = 0;
8718 rsurface.batchelement3i = NULL;
8719 rsurface.batchelement3i_indexbuffer = NULL;
8720 rsurface.batchelement3i_bufferoffset = 0;
8721 rsurface.batchelement3s = NULL;
8722 rsurface.batchelement3s_indexbuffer = NULL;
8723 rsurface.batchelement3s_bufferoffset = 0;
8724 rsurface.passcolor4f = NULL;
8725 rsurface.passcolor4f_vertexbuffer = NULL;
8726 rsurface.passcolor4f_bufferoffset = 0;
8727 rsurface.forcecurrenttextureupdate = false;
8730 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)
8732 rsurface.entity = r_refdef.scene.worldentity;
8733 rsurface.skeleton = NULL;
8734 rsurface.ent_skinnum = 0;
8735 rsurface.ent_qwskin = -1;
8736 rsurface.ent_flags = entflags;
8737 rsurface.shadertime = r_refdef.scene.time - shadertime;
8738 rsurface.modelnumvertices = numvertices;
8739 rsurface.modelnumtriangles = numtriangles;
8740 rsurface.matrix = *matrix;
8741 rsurface.inversematrix = *inversematrix;
8742 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8743 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8744 R_EntityMatrix(&rsurface.matrix);
8745 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8746 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8747 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8748 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8749 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8750 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8751 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8752 rsurface.frameblend[0].lerp = 1;
8753 rsurface.ent_alttextures = false;
8754 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8755 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8756 rsurface.entityskeletaltransform3x4 = NULL;
8757 rsurface.entityskeletaltransform3x4buffer = NULL;
8758 rsurface.entityskeletaltransform3x4offset = 0;
8759 rsurface.entityskeletaltransform3x4size = 0;
8760 rsurface.entityskeletalnumtransforms = 0;
8761 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8762 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8763 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8764 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8767 rsurface.modelvertex3f = (float *)vertex3f;
8768 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8769 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8770 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8772 else if (wantnormals)
8774 rsurface.modelvertex3f = (float *)vertex3f;
8775 rsurface.modelsvector3f = NULL;
8776 rsurface.modeltvector3f = NULL;
8777 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8781 rsurface.modelvertex3f = (float *)vertex3f;
8782 rsurface.modelsvector3f = NULL;
8783 rsurface.modeltvector3f = NULL;
8784 rsurface.modelnormal3f = NULL;
8786 rsurface.modelvertexmesh = NULL;
8787 rsurface.modelvertexmesh_vertexbuffer = NULL;
8788 rsurface.modelvertexmesh_bufferoffset = 0;
8789 rsurface.modelvertex3f_vertexbuffer = 0;
8790 rsurface.modelvertex3f_bufferoffset = 0;
8791 rsurface.modelsvector3f_vertexbuffer = 0;
8792 rsurface.modelsvector3f_bufferoffset = 0;
8793 rsurface.modeltvector3f_vertexbuffer = 0;
8794 rsurface.modeltvector3f_bufferoffset = 0;
8795 rsurface.modelnormal3f_vertexbuffer = 0;
8796 rsurface.modelnormal3f_bufferoffset = 0;
8797 rsurface.modelgeneratedvertex = true;
8798 rsurface.modellightmapcolor4f = (float *)color4f;
8799 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8800 rsurface.modellightmapcolor4f_bufferoffset = 0;
8801 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8802 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8803 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8804 rsurface.modeltexcoordlightmap2f = NULL;
8805 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8806 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8807 rsurface.modelskeletalindex4ub = NULL;
8808 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8809 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8810 rsurface.modelskeletalweight4ub = NULL;
8811 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8812 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8813 rsurface.modelelement3i = (int *)element3i;
8814 rsurface.modelelement3i_indexbuffer = NULL;
8815 rsurface.modelelement3i_bufferoffset = 0;
8816 rsurface.modelelement3s = (unsigned short *)element3s;
8817 rsurface.modelelement3s_indexbuffer = NULL;
8818 rsurface.modelelement3s_bufferoffset = 0;
8819 rsurface.modellightmapoffsets = NULL;
8820 rsurface.modelsurfaces = NULL;
8821 rsurface.batchgeneratedvertex = false;
8822 rsurface.batchfirstvertex = 0;
8823 rsurface.batchnumvertices = 0;
8824 rsurface.batchfirsttriangle = 0;
8825 rsurface.batchnumtriangles = 0;
8826 rsurface.batchvertex3f = NULL;
8827 rsurface.batchvertex3f_vertexbuffer = NULL;
8828 rsurface.batchvertex3f_bufferoffset = 0;
8829 rsurface.batchsvector3f = NULL;
8830 rsurface.batchsvector3f_vertexbuffer = NULL;
8831 rsurface.batchsvector3f_bufferoffset = 0;
8832 rsurface.batchtvector3f = NULL;
8833 rsurface.batchtvector3f_vertexbuffer = NULL;
8834 rsurface.batchtvector3f_bufferoffset = 0;
8835 rsurface.batchnormal3f = NULL;
8836 rsurface.batchnormal3f_vertexbuffer = NULL;
8837 rsurface.batchnormal3f_bufferoffset = 0;
8838 rsurface.batchlightmapcolor4f = NULL;
8839 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8840 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8841 rsurface.batchtexcoordtexture2f = NULL;
8842 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8843 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8844 rsurface.batchtexcoordlightmap2f = NULL;
8845 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8846 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8847 rsurface.batchskeletalindex4ub = NULL;
8848 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8849 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8850 rsurface.batchskeletalweight4ub = NULL;
8851 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8852 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8853 rsurface.batchvertexmesh = NULL;
8854 rsurface.batchvertexmesh_vertexbuffer = NULL;
8855 rsurface.batchvertexmesh_bufferoffset = 0;
8856 rsurface.batchelement3i = NULL;
8857 rsurface.batchelement3i_indexbuffer = NULL;
8858 rsurface.batchelement3i_bufferoffset = 0;
8859 rsurface.batchelement3s = NULL;
8860 rsurface.batchelement3s_indexbuffer = NULL;
8861 rsurface.batchelement3s_bufferoffset = 0;
8862 rsurface.passcolor4f = NULL;
8863 rsurface.passcolor4f_vertexbuffer = NULL;
8864 rsurface.passcolor4f_bufferoffset = 0;
8865 rsurface.forcecurrenttextureupdate = true;
8867 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8869 if ((wantnormals || wanttangents) && !normal3f)
8871 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8872 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8874 if (wanttangents && !svector3f)
8876 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8877 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8878 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8883 float RSurf_FogPoint(const float *v)
8885 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8886 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8887 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8888 float FogHeightFade = r_refdef.fogheightfade;
8890 unsigned int fogmasktableindex;
8891 if (r_refdef.fogplaneviewabove)
8892 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8894 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8895 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8896 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8899 float RSurf_FogVertex(const float *v)
8901 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8902 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8903 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8904 float FogHeightFade = rsurface.fogheightfade;
8906 unsigned int fogmasktableindex;
8907 if (r_refdef.fogplaneviewabove)
8908 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8910 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8911 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8912 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8915 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8918 for (i = 0;i < numelements;i++)
8919 outelement3i[i] = inelement3i[i] + adjust;
8922 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8923 extern cvar_t gl_vbo;
8924 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8932 int surfacefirsttriangle;
8933 int surfacenumtriangles;
8934 int surfacefirstvertex;
8935 int surfaceendvertex;
8936 int surfacenumvertices;
8937 int batchnumsurfaces = texturenumsurfaces;
8938 int batchnumvertices;
8939 int batchnumtriangles;
8943 qboolean dynamicvertex;
8946 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8949 q3shaderinfo_deform_t *deform;
8950 const msurface_t *surface, *firstsurface;
8951 r_vertexmesh_t *vertexmesh;
8952 if (!texturenumsurfaces)
8954 // find vertex range of this surface batch
8956 firstsurface = texturesurfacelist[0];
8957 firsttriangle = firstsurface->num_firsttriangle;
8958 batchnumvertices = 0;
8959 batchnumtriangles = 0;
8960 firstvertex = endvertex = firstsurface->num_firstvertex;
8961 for (i = 0;i < texturenumsurfaces;i++)
8963 surface = texturesurfacelist[i];
8964 if (surface != firstsurface + i)
8966 surfacefirstvertex = surface->num_firstvertex;
8967 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8968 surfacenumvertices = surface->num_vertices;
8969 surfacenumtriangles = surface->num_triangles;
8970 if (firstvertex > surfacefirstvertex)
8971 firstvertex = surfacefirstvertex;
8972 if (endvertex < surfaceendvertex)
8973 endvertex = surfaceendvertex;
8974 batchnumvertices += surfacenumvertices;
8975 batchnumtriangles += surfacenumtriangles;
8978 r_refdef.stats[r_stat_batch_batches]++;
8980 r_refdef.stats[r_stat_batch_withgaps]++;
8981 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8982 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8983 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8985 // we now know the vertex range used, and if there are any gaps in it
8986 rsurface.batchfirstvertex = firstvertex;
8987 rsurface.batchnumvertices = endvertex - firstvertex;
8988 rsurface.batchfirsttriangle = firsttriangle;
8989 rsurface.batchnumtriangles = batchnumtriangles;
8991 // this variable holds flags for which properties have been updated that
8992 // may require regenerating vertexmesh array...
8995 // check if any dynamic vertex processing must occur
8996 dynamicvertex = false;
8998 // a cvar to force the dynamic vertex path to be taken, for debugging
8999 if (r_batch_debugdynamicvertexpath.integer)
9003 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9004 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9005 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9006 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9008 dynamicvertex = true;
9011 // if there is a chance of animated vertex colors, it's a dynamic batch
9012 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9016 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9017 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9018 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9019 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9021 dynamicvertex = true;
9022 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9025 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9027 switch (deform->deform)
9030 case Q3DEFORM_PROJECTIONSHADOW:
9031 case Q3DEFORM_TEXT0:
9032 case Q3DEFORM_TEXT1:
9033 case Q3DEFORM_TEXT2:
9034 case Q3DEFORM_TEXT3:
9035 case Q3DEFORM_TEXT4:
9036 case Q3DEFORM_TEXT5:
9037 case Q3DEFORM_TEXT6:
9038 case Q3DEFORM_TEXT7:
9041 case Q3DEFORM_AUTOSPRITE:
9044 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9045 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9046 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9047 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9049 dynamicvertex = true;
9050 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9051 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9053 case Q3DEFORM_AUTOSPRITE2:
9056 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9057 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9058 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9059 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9061 dynamicvertex = true;
9062 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9063 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9065 case Q3DEFORM_NORMAL:
9068 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9069 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9070 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9071 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9073 dynamicvertex = true;
9074 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9075 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9078 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9079 break; // if wavefunc is a nop, ignore this transform
9082 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9083 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9084 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9085 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9087 dynamicvertex = true;
9088 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9089 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9091 case Q3DEFORM_BULGE:
9094 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9095 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9096 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9097 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9099 dynamicvertex = true;
9100 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9101 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9104 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9105 break; // if wavefunc is a nop, ignore this transform
9108 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9109 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9110 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9111 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9113 dynamicvertex = true;
9114 batchneed |= BATCHNEED_ARRAY_VERTEX;
9115 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9119 if (rsurface.texture->materialshaderpass)
9121 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9124 case Q3TCGEN_TEXTURE:
9126 case Q3TCGEN_LIGHTMAP:
9129 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9130 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9131 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9132 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9134 dynamicvertex = true;
9135 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9136 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9138 case Q3TCGEN_VECTOR:
9141 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9142 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9143 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9144 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9146 dynamicvertex = true;
9147 batchneed |= BATCHNEED_ARRAY_VERTEX;
9148 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9150 case Q3TCGEN_ENVIRONMENT:
9153 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9154 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9155 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9156 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9158 dynamicvertex = true;
9159 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9160 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9163 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9167 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9168 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9169 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9170 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9172 dynamicvertex = true;
9173 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9174 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9178 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9182 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9183 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9184 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9185 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9187 dynamicvertex = true;
9188 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9191 // when the model data has no vertex buffer (dynamic mesh), we need to
9193 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9194 batchneed |= BATCHNEED_NOGAPS;
9196 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9197 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9198 // we ensure this by treating the vertex batch as dynamic...
9199 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9203 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9204 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9205 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9206 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9208 dynamicvertex = true;
9213 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9214 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9215 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9216 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9217 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9218 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9219 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9220 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9223 // if needsupdate, we have to do a dynamic vertex batch for sure
9224 if (needsupdate & batchneed)
9228 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9229 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9230 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9231 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9233 dynamicvertex = true;
9236 // see if we need to build vertexmesh from arrays
9237 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9241 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9242 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9243 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9244 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9246 dynamicvertex = true;
9249 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9250 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9251 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9253 rsurface.batchvertex3f = rsurface.modelvertex3f;
9254 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9255 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9256 rsurface.batchsvector3f = rsurface.modelsvector3f;
9257 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9258 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9259 rsurface.batchtvector3f = rsurface.modeltvector3f;
9260 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9261 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9262 rsurface.batchnormal3f = rsurface.modelnormal3f;
9263 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9264 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9265 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9266 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9267 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9268 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9269 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9270 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9271 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9272 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9273 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9274 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9275 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9276 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9277 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9278 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9279 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9280 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9281 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9282 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9283 rsurface.batchelement3i = rsurface.modelelement3i;
9284 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9285 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9286 rsurface.batchelement3s = rsurface.modelelement3s;
9287 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9288 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9289 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9290 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9291 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9292 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9293 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9295 // if any dynamic vertex processing has to occur in software, we copy the
9296 // entire surface list together before processing to rebase the vertices
9297 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9299 // if any gaps exist and we do not have a static vertex buffer, we have to
9300 // copy the surface list together to avoid wasting upload bandwidth on the
9301 // vertices in the gaps.
9303 // if gaps exist and we have a static vertex buffer, we can choose whether
9304 // to combine the index buffer ranges into one dynamic index buffer or
9305 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9307 // in many cases the batch is reduced to one draw call.
9309 rsurface.batchmultidraw = false;
9310 rsurface.batchmultidrawnumsurfaces = 0;
9311 rsurface.batchmultidrawsurfacelist = NULL;
9315 // static vertex data, just set pointers...
9316 rsurface.batchgeneratedvertex = false;
9317 // if there are gaps, we want to build a combined index buffer,
9318 // otherwise use the original static buffer with an appropriate offset
9321 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9322 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9323 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9324 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9325 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9327 rsurface.batchmultidraw = true;
9328 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9329 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9332 // build a new triangle elements array for this batch
9333 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9334 rsurface.batchfirsttriangle = 0;
9336 for (i = 0;i < texturenumsurfaces;i++)
9338 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9339 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9340 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9341 numtriangles += surfacenumtriangles;
9343 rsurface.batchelement3i_indexbuffer = NULL;
9344 rsurface.batchelement3i_bufferoffset = 0;
9345 rsurface.batchelement3s = NULL;
9346 rsurface.batchelement3s_indexbuffer = NULL;
9347 rsurface.batchelement3s_bufferoffset = 0;
9348 if (endvertex <= 65536)
9350 // make a 16bit (unsigned short) index array if possible
9351 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9352 for (i = 0;i < numtriangles*3;i++)
9353 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9355 // upload buffer data for the copytriangles batch
9356 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9358 if (rsurface.batchelement3s)
9359 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9360 else if (rsurface.batchelement3i)
9361 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9366 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9367 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9368 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9369 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9374 // something needs software processing, do it for real...
9375 // we only directly handle separate array data in this case and then
9376 // generate interleaved data if needed...
9377 rsurface.batchgeneratedvertex = true;
9378 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9379 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9380 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9381 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9383 // now copy the vertex data into a combined array and make an index array
9384 // (this is what Quake3 does all the time)
9385 // we also apply any skeletal animation here that would have been done in
9386 // the vertex shader, because most of the dynamic vertex animation cases
9387 // need actual vertex positions and normals
9388 //if (dynamicvertex)
9390 rsurface.batchvertexmesh = NULL;
9391 rsurface.batchvertexmesh_vertexbuffer = NULL;
9392 rsurface.batchvertexmesh_bufferoffset = 0;
9393 rsurface.batchvertex3f = NULL;
9394 rsurface.batchvertex3f_vertexbuffer = NULL;
9395 rsurface.batchvertex3f_bufferoffset = 0;
9396 rsurface.batchsvector3f = NULL;
9397 rsurface.batchsvector3f_vertexbuffer = NULL;
9398 rsurface.batchsvector3f_bufferoffset = 0;
9399 rsurface.batchtvector3f = NULL;
9400 rsurface.batchtvector3f_vertexbuffer = NULL;
9401 rsurface.batchtvector3f_bufferoffset = 0;
9402 rsurface.batchnormal3f = NULL;
9403 rsurface.batchnormal3f_vertexbuffer = NULL;
9404 rsurface.batchnormal3f_bufferoffset = 0;
9405 rsurface.batchlightmapcolor4f = NULL;
9406 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9407 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9408 rsurface.batchtexcoordtexture2f = NULL;
9409 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9410 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9411 rsurface.batchtexcoordlightmap2f = NULL;
9412 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9413 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9414 rsurface.batchskeletalindex4ub = NULL;
9415 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9416 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9417 rsurface.batchskeletalweight4ub = NULL;
9418 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9419 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9420 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9421 rsurface.batchelement3i_indexbuffer = NULL;
9422 rsurface.batchelement3i_bufferoffset = 0;
9423 rsurface.batchelement3s = NULL;
9424 rsurface.batchelement3s_indexbuffer = NULL;
9425 rsurface.batchelement3s_bufferoffset = 0;
9426 rsurface.batchskeletaltransform3x4buffer = NULL;
9427 rsurface.batchskeletaltransform3x4offset = 0;
9428 rsurface.batchskeletaltransform3x4size = 0;
9429 // we'll only be setting up certain arrays as needed
9430 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9431 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9432 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9433 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9434 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9435 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9436 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9438 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9439 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9441 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9442 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9443 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9444 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9445 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9446 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9447 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9449 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9450 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9454 for (i = 0;i < texturenumsurfaces;i++)
9456 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9457 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9458 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9459 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9460 // copy only the data requested
9461 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9462 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9463 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9465 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9467 if (rsurface.batchvertex3f)
9468 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9470 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9472 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9474 if (rsurface.modelnormal3f)
9475 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9477 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9479 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9481 if (rsurface.modelsvector3f)
9483 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9484 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9488 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9489 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9492 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9494 if (rsurface.modellightmapcolor4f)
9495 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9497 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9499 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9501 if (rsurface.modeltexcoordtexture2f)
9502 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9504 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9506 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9508 if (rsurface.modeltexcoordlightmap2f)
9509 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9511 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9513 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9515 if (rsurface.modelskeletalindex4ub)
9517 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9518 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9522 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9523 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9524 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9525 for (j = 0;j < surfacenumvertices;j++)
9530 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9531 numvertices += surfacenumvertices;
9532 numtriangles += surfacenumtriangles;
9535 // generate a 16bit index array as well if possible
9536 // (in general, dynamic batches fit)
9537 if (numvertices <= 65536)
9539 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9540 for (i = 0;i < numtriangles*3;i++)
9541 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9544 // since we've copied everything, the batch now starts at 0
9545 rsurface.batchfirstvertex = 0;
9546 rsurface.batchnumvertices = batchnumvertices;
9547 rsurface.batchfirsttriangle = 0;
9548 rsurface.batchnumtriangles = batchnumtriangles;
9551 // apply skeletal animation that would have been done in the vertex shader
9552 if (rsurface.batchskeletaltransform3x4)
9554 const unsigned char *si;
9555 const unsigned char *sw;
9557 const float *b = rsurface.batchskeletaltransform3x4;
9558 float *vp, *vs, *vt, *vn;
9560 float m[3][4], n[3][4];
9561 float tp[3], ts[3], tt[3], tn[3];
9562 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9563 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9564 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9565 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9566 si = rsurface.batchskeletalindex4ub;
9567 sw = rsurface.batchskeletalweight4ub;
9568 vp = rsurface.batchvertex3f;
9569 vs = rsurface.batchsvector3f;
9570 vt = rsurface.batchtvector3f;
9571 vn = rsurface.batchnormal3f;
9572 memset(m[0], 0, sizeof(m));
9573 memset(n[0], 0, sizeof(n));
9574 for (i = 0;i < batchnumvertices;i++)
9576 t[0] = b + si[0]*12;
9579 // common case - only one matrix
9593 else if (sw[2] + sw[3])
9596 t[1] = b + si[1]*12;
9597 t[2] = b + si[2]*12;
9598 t[3] = b + si[3]*12;
9599 w[0] = sw[0] * (1.0f / 255.0f);
9600 w[1] = sw[1] * (1.0f / 255.0f);
9601 w[2] = sw[2] * (1.0f / 255.0f);
9602 w[3] = sw[3] * (1.0f / 255.0f);
9603 // blend the matrices
9604 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9605 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9606 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9607 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9608 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9609 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9610 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9611 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9612 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9613 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9614 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9615 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9620 t[1] = b + si[1]*12;
9621 w[0] = sw[0] * (1.0f / 255.0f);
9622 w[1] = sw[1] * (1.0f / 255.0f);
9623 // blend the matrices
9624 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9625 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9626 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9627 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9628 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9629 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9630 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9631 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9632 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9633 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9634 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9635 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9639 // modify the vertex
9641 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9642 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9643 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9647 // the normal transformation matrix is a set of cross products...
9648 CrossProduct(m[1], m[2], n[0]);
9649 CrossProduct(m[2], m[0], n[1]);
9650 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9652 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9653 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9654 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9655 VectorNormalize(vn);
9660 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9661 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9662 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9663 VectorNormalize(vs);
9666 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9667 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9668 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9669 VectorNormalize(vt);
9674 rsurface.batchskeletaltransform3x4 = NULL;
9675 rsurface.batchskeletalnumtransforms = 0;
9678 // q1bsp surfaces rendered in vertex color mode have to have colors
9679 // calculated based on lightstyles
9680 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9682 // generate color arrays for the surfaces in this list
9687 const unsigned char *lm;
9688 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9689 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9690 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9692 for (i = 0;i < texturenumsurfaces;i++)
9694 surface = texturesurfacelist[i];
9695 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9696 surfacenumvertices = surface->num_vertices;
9697 if (surface->lightmapinfo->samples)
9699 for (j = 0;j < surfacenumvertices;j++)
9701 lm = surface->lightmapinfo->samples + offsets[j];
9702 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9703 VectorScale(lm, scale, c);
9704 if (surface->lightmapinfo->styles[1] != 255)
9706 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9708 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9709 VectorMA(c, scale, lm, c);
9710 if (surface->lightmapinfo->styles[2] != 255)
9713 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9714 VectorMA(c, scale, lm, c);
9715 if (surface->lightmapinfo->styles[3] != 255)
9718 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9719 VectorMA(c, scale, lm, c);
9726 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);
9732 for (j = 0;j < surfacenumvertices;j++)
9734 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9741 // if vertices are deformed (sprite flares and things in maps, possibly
9742 // water waves, bulges and other deformations), modify the copied vertices
9744 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9747 switch (deform->deform)
9750 case Q3DEFORM_PROJECTIONSHADOW:
9751 case Q3DEFORM_TEXT0:
9752 case Q3DEFORM_TEXT1:
9753 case Q3DEFORM_TEXT2:
9754 case Q3DEFORM_TEXT3:
9755 case Q3DEFORM_TEXT4:
9756 case Q3DEFORM_TEXT5:
9757 case Q3DEFORM_TEXT6:
9758 case Q3DEFORM_TEXT7:
9761 case Q3DEFORM_AUTOSPRITE:
9762 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9763 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9764 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9765 VectorNormalize(newforward);
9766 VectorNormalize(newright);
9767 VectorNormalize(newup);
9768 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9769 // rsurface.batchvertex3f_vertexbuffer = NULL;
9770 // rsurface.batchvertex3f_bufferoffset = 0;
9771 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9772 // rsurface.batchsvector3f_vertexbuffer = NULL;
9773 // rsurface.batchsvector3f_bufferoffset = 0;
9774 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9775 // rsurface.batchtvector3f_vertexbuffer = NULL;
9776 // rsurface.batchtvector3f_bufferoffset = 0;
9777 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9778 // rsurface.batchnormal3f_vertexbuffer = NULL;
9779 // rsurface.batchnormal3f_bufferoffset = 0;
9780 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9781 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9782 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9783 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9784 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);
9785 // a single autosprite surface can contain multiple sprites...
9786 for (j = 0;j < batchnumvertices - 3;j += 4)
9788 VectorClear(center);
9789 for (i = 0;i < 4;i++)
9790 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9791 VectorScale(center, 0.25f, center);
9792 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9793 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9794 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9795 for (i = 0;i < 4;i++)
9797 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9798 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9801 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9802 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9803 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);
9805 case Q3DEFORM_AUTOSPRITE2:
9806 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9807 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9808 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9809 VectorNormalize(newforward);
9810 VectorNormalize(newright);
9811 VectorNormalize(newup);
9812 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9813 // rsurface.batchvertex3f_vertexbuffer = NULL;
9814 // rsurface.batchvertex3f_bufferoffset = 0;
9816 const float *v1, *v2;
9826 memset(shortest, 0, sizeof(shortest));
9827 // a single autosprite surface can contain multiple sprites...
9828 for (j = 0;j < batchnumvertices - 3;j += 4)
9830 VectorClear(center);
9831 for (i = 0;i < 4;i++)
9832 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9833 VectorScale(center, 0.25f, center);
9834 // find the two shortest edges, then use them to define the
9835 // axis vectors for rotating around the central axis
9836 for (i = 0;i < 6;i++)
9838 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9839 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9840 l = VectorDistance2(v1, v2);
9841 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9843 l += (1.0f / 1024.0f);
9844 if (shortest[0].length2 > l || i == 0)
9846 shortest[1] = shortest[0];
9847 shortest[0].length2 = l;
9848 shortest[0].v1 = v1;
9849 shortest[0].v2 = v2;
9851 else if (shortest[1].length2 > l || i == 1)
9853 shortest[1].length2 = l;
9854 shortest[1].v1 = v1;
9855 shortest[1].v2 = v2;
9858 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9859 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9860 // this calculates the right vector from the shortest edge
9861 // and the up vector from the edge midpoints
9862 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9863 VectorNormalize(right);
9864 VectorSubtract(end, start, up);
9865 VectorNormalize(up);
9866 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9867 VectorSubtract(rsurface.localvieworigin, center, forward);
9868 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9869 VectorNegate(forward, forward);
9870 VectorReflect(forward, 0, up, forward);
9871 VectorNormalize(forward);
9872 CrossProduct(up, forward, newright);
9873 VectorNormalize(newright);
9874 // rotate the quad around the up axis vector, this is made
9875 // especially easy by the fact we know the quad is flat,
9876 // so we only have to subtract the center position and
9877 // measure distance along the right vector, and then
9878 // multiply that by the newright vector and add back the
9880 // we also need to subtract the old position to undo the
9881 // displacement from the center, which we do with a
9882 // DotProduct, the subtraction/addition of center is also
9883 // optimized into DotProducts here
9884 l = DotProduct(right, center);
9885 for (i = 0;i < 4;i++)
9887 v1 = rsurface.batchvertex3f + 3*(j+i);
9888 f = DotProduct(right, v1) - l;
9889 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9893 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9895 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9896 // rsurface.batchnormal3f_vertexbuffer = NULL;
9897 // rsurface.batchnormal3f_bufferoffset = 0;
9898 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9900 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9902 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9903 // rsurface.batchsvector3f_vertexbuffer = NULL;
9904 // rsurface.batchsvector3f_bufferoffset = 0;
9905 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9906 // rsurface.batchtvector3f_vertexbuffer = NULL;
9907 // rsurface.batchtvector3f_bufferoffset = 0;
9908 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);
9911 case Q3DEFORM_NORMAL:
9912 // deform the normals to make reflections wavey
9913 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9914 rsurface.batchnormal3f_vertexbuffer = NULL;
9915 rsurface.batchnormal3f_bufferoffset = 0;
9916 for (j = 0;j < batchnumvertices;j++)
9919 float *normal = rsurface.batchnormal3f + 3*j;
9920 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9921 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9922 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9923 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9924 VectorNormalize(normal);
9926 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9928 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9929 // rsurface.batchsvector3f_vertexbuffer = NULL;
9930 // rsurface.batchsvector3f_bufferoffset = 0;
9931 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9932 // rsurface.batchtvector3f_vertexbuffer = NULL;
9933 // rsurface.batchtvector3f_bufferoffset = 0;
9934 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);
9938 // deform vertex array to make wavey water and flags and such
9939 waveparms[0] = deform->waveparms[0];
9940 waveparms[1] = deform->waveparms[1];
9941 waveparms[2] = deform->waveparms[2];
9942 waveparms[3] = deform->waveparms[3];
9943 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9944 break; // if wavefunc is a nop, don't make a dynamic vertex array
9945 // this is how a divisor of vertex influence on deformation
9946 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9947 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9948 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9949 // rsurface.batchvertex3f_vertexbuffer = NULL;
9950 // rsurface.batchvertex3f_bufferoffset = 0;
9951 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9952 // rsurface.batchnormal3f_vertexbuffer = NULL;
9953 // rsurface.batchnormal3f_bufferoffset = 0;
9954 for (j = 0;j < batchnumvertices;j++)
9956 // if the wavefunc depends on time, evaluate it per-vertex
9959 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9960 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9962 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9964 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9965 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9966 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9968 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9969 // rsurface.batchsvector3f_vertexbuffer = NULL;
9970 // rsurface.batchsvector3f_bufferoffset = 0;
9971 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9972 // rsurface.batchtvector3f_vertexbuffer = NULL;
9973 // rsurface.batchtvector3f_bufferoffset = 0;
9974 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);
9977 case Q3DEFORM_BULGE:
9978 // deform vertex array to make the surface have moving bulges
9979 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9980 // rsurface.batchvertex3f_vertexbuffer = NULL;
9981 // rsurface.batchvertex3f_bufferoffset = 0;
9982 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9983 // rsurface.batchnormal3f_vertexbuffer = NULL;
9984 // rsurface.batchnormal3f_bufferoffset = 0;
9985 for (j = 0;j < batchnumvertices;j++)
9987 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9988 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9990 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9991 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9992 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9994 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9995 // rsurface.batchsvector3f_vertexbuffer = NULL;
9996 // rsurface.batchsvector3f_bufferoffset = 0;
9997 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9998 // rsurface.batchtvector3f_vertexbuffer = NULL;
9999 // rsurface.batchtvector3f_bufferoffset = 0;
10000 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);
10003 case Q3DEFORM_MOVE:
10004 // deform vertex array
10005 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10006 break; // if wavefunc is a nop, don't make a dynamic vertex array
10007 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10008 VectorScale(deform->parms, scale, waveparms);
10009 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10010 // rsurface.batchvertex3f_vertexbuffer = NULL;
10011 // rsurface.batchvertex3f_bufferoffset = 0;
10012 for (j = 0;j < batchnumvertices;j++)
10013 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10018 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10020 // generate texcoords based on the chosen texcoord source
10021 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10024 case Q3TCGEN_TEXTURE:
10026 case Q3TCGEN_LIGHTMAP:
10027 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10028 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10029 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10030 if (rsurface.batchtexcoordlightmap2f)
10031 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10033 case Q3TCGEN_VECTOR:
10034 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10035 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10036 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10037 for (j = 0;j < batchnumvertices;j++)
10039 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10040 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10043 case Q3TCGEN_ENVIRONMENT:
10044 // make environment reflections using a spheremap
10045 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10046 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10047 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10048 for (j = 0;j < batchnumvertices;j++)
10050 // identical to Q3A's method, but executed in worldspace so
10051 // carried models can be shiny too
10053 float viewer[3], d, reflected[3], worldreflected[3];
10055 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10056 // VectorNormalize(viewer);
10058 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10060 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10061 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10062 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10063 // note: this is proportinal to viewer, so we can normalize later
10065 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10066 VectorNormalize(worldreflected);
10068 // note: this sphere map only uses world x and z!
10069 // so positive and negative y will LOOK THE SAME.
10070 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10071 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10075 // the only tcmod that needs software vertex processing is turbulent, so
10076 // check for it here and apply the changes if needed
10077 // and we only support that as the first one
10078 // (handling a mixture of turbulent and other tcmods would be problematic
10079 // without punting it entirely to a software path)
10080 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10082 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10083 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10084 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10085 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10086 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10087 for (j = 0;j < batchnumvertices;j++)
10089 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);
10090 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10095 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10097 // convert the modified arrays to vertex structs
10098 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10099 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10100 // rsurface.batchvertexmesh_bufferoffset = 0;
10101 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10102 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10103 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10104 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10105 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10106 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10107 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10109 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10111 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10112 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10115 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10116 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10117 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10118 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10119 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10120 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10121 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10122 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10123 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10124 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10126 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10128 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10129 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10134 // upload buffer data for the dynamic batch
10135 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10137 if (rsurface.batchvertexmesh)
10138 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10141 if (rsurface.batchvertex3f)
10142 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10143 if (rsurface.batchsvector3f)
10144 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10145 if (rsurface.batchtvector3f)
10146 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10147 if (rsurface.batchnormal3f)
10148 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10149 if (rsurface.batchlightmapcolor4f)
10150 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10151 if (rsurface.batchtexcoordtexture2f)
10152 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10153 if (rsurface.batchtexcoordlightmap2f)
10154 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10155 if (rsurface.batchskeletalindex4ub)
10156 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10157 if (rsurface.batchskeletalweight4ub)
10158 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10160 if (rsurface.batchelement3s)
10161 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10162 else if (rsurface.batchelement3i)
10163 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10167 void RSurf_DrawBatch(void)
10169 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10170 // through the pipeline, killing it earlier in the pipeline would have
10171 // per-surface overhead rather than per-batch overhead, so it's best to
10172 // reject it here, before it hits glDraw.
10173 if (rsurface.batchnumtriangles == 0)
10176 // batch debugging code
10177 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10183 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10184 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10187 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10189 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10191 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10192 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);
10199 if (rsurface.batchmultidraw)
10201 // issue multiple draws rather than copying index data
10202 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10203 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10204 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10205 for (i = 0;i < numsurfaces;)
10207 // combine consecutive surfaces as one draw
10208 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10209 if (surfacelist[j] != surfacelist[k] + 1)
10211 firstvertex = surfacelist[i]->num_firstvertex;
10212 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10213 firsttriangle = surfacelist[i]->num_firsttriangle;
10214 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10215 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);
10221 // there is only one consecutive run of index data (may have been combined)
10222 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);
10226 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10228 // pick the closest matching water plane
10229 int planeindex, vertexindex, bestplaneindex = -1;
10233 r_waterstate_waterplane_t *p;
10234 qboolean prepared = false;
10236 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10238 if(p->camera_entity != rsurface.texture->camera_entity)
10243 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10245 if(rsurface.batchnumvertices == 0)
10248 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10250 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10251 d += fabs(PlaneDiff(vert, &p->plane));
10253 if (bestd > d || bestplaneindex < 0)
10256 bestplaneindex = planeindex;
10259 return bestplaneindex;
10260 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10261 // this situation though, as it might be better to render single larger
10262 // batches with useless stuff (backface culled for example) than to
10263 // render multiple smaller batches
10266 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10269 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10270 rsurface.passcolor4f_vertexbuffer = 0;
10271 rsurface.passcolor4f_bufferoffset = 0;
10272 for (i = 0;i < rsurface.batchnumvertices;i++)
10273 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10276 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10283 if (rsurface.passcolor4f)
10285 // generate color arrays
10286 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10287 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10288 rsurface.passcolor4f_vertexbuffer = 0;
10289 rsurface.passcolor4f_bufferoffset = 0;
10290 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)
10292 f = RSurf_FogVertex(v);
10301 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10302 rsurface.passcolor4f_vertexbuffer = 0;
10303 rsurface.passcolor4f_bufferoffset = 0;
10304 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10306 f = RSurf_FogVertex(v);
10315 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10322 if (!rsurface.passcolor4f)
10324 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10325 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10326 rsurface.passcolor4f_vertexbuffer = 0;
10327 rsurface.passcolor4f_bufferoffset = 0;
10328 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)
10330 f = RSurf_FogVertex(v);
10331 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10332 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10333 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10338 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
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, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10358 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10363 if (!rsurface.passcolor4f)
10365 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10366 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10367 rsurface.passcolor4f_vertexbuffer = 0;
10368 rsurface.passcolor4f_bufferoffset = 0;
10369 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10371 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10372 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10373 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10378 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10381 rsurface.passcolor4f = NULL;
10382 rsurface.passcolor4f_vertexbuffer = 0;
10383 rsurface.passcolor4f_bufferoffset = 0;
10384 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10385 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10386 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10387 GL_Color(r, g, b, a);
10388 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10389 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10390 R_Mesh_TexMatrix(0, NULL);
10394 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10396 // TODO: optimize applyfog && applycolor case
10397 // just apply fog if necessary, and tint the fog color array if necessary
10398 rsurface.passcolor4f = NULL;
10399 rsurface.passcolor4f_vertexbuffer = 0;
10400 rsurface.passcolor4f_bufferoffset = 0;
10401 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10402 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10403 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10404 GL_Color(r, g, b, a);
10408 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10411 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10412 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10413 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10414 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10415 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10416 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10417 GL_Color(r, g, b, a);
10421 static void RSurf_DrawBatch_GL11_ClampColor(void)
10426 if (!rsurface.passcolor4f)
10428 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10430 c2[0] = bound(0.0f, c1[0], 1.0f);
10431 c2[1] = bound(0.0f, c1[1], 1.0f);
10432 c2[2] = bound(0.0f, c1[2], 1.0f);
10433 c2[3] = bound(0.0f, c1[3], 1.0f);
10437 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10447 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10448 rsurface.passcolor4f_vertexbuffer = 0;
10449 rsurface.passcolor4f_bufferoffset = 0;
10450 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)
10452 f = -DotProduct(r_refdef.view.forward, n);
10454 f = f * 0.85 + 0.15; // work around so stuff won't get black
10455 f *= fakelightintensity;
10456 Vector4Set(c, f, f, f, 1);
10460 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10462 RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10463 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10464 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10465 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10466 GL_Color(r, g, b, a);
10470 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10478 vec3_t ambientcolor;
10479 vec3_t diffusecolor;
10483 VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10484 f = 0.5f * lightmapintensity;
10485 ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10486 ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10487 ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10488 diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10489 diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10490 diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10492 if (VectorLength2(diffusecolor) > 0)
10494 // q3-style directional shading
10495 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10496 rsurface.passcolor4f_vertexbuffer = 0;
10497 rsurface.passcolor4f_bufferoffset = 0;
10498 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)
10500 if ((f = DotProduct(n, lightdir)) > 0)
10501 VectorMA(ambientcolor, f, diffusecolor, c);
10503 VectorCopy(ambientcolor, c);
10510 *applycolor = false;
10514 *r = ambientcolor[0];
10515 *g = ambientcolor[1];
10516 *b = ambientcolor[2];
10517 rsurface.passcolor4f = NULL;
10518 rsurface.passcolor4f_vertexbuffer = 0;
10519 rsurface.passcolor4f_bufferoffset = 0;
10523 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10525 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10526 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10527 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10528 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10529 GL_Color(r, g, b, a);
10533 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10541 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10542 rsurface.passcolor4f_vertexbuffer = 0;
10543 rsurface.passcolor4f_bufferoffset = 0;
10545 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10547 f = 1 - RSurf_FogVertex(v);
10555 void RSurf_SetupDepthAndCulling(void)
10557 // submodels are biased to avoid z-fighting with world surfaces that they
10558 // may be exactly overlapping (avoids z-fighting artifacts on certain
10559 // doors and things in Quake maps)
10560 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10561 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10562 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10563 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10566 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10569 // transparent sky would be ridiculous
10570 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10572 R_SetupShader_Generic_NoTexture(false, false);
10573 skyrenderlater = true;
10574 RSurf_SetupDepthAndCulling();
10575 GL_DepthMask(true);
10577 // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10578 if (r_sky_scissor.integer)
10580 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10581 for (i = 0; i < texturenumsurfaces; i++)
10583 const msurface_t *surf = texturesurfacelist[i];
10586 float mins[3], maxs[3];
10588 for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10590 Matrix4x4_Transform(&rsurface.matrix, v, p);
10593 if (mins[0] > p[0]) mins[0] = p[0];
10594 if (mins[1] > p[1]) mins[1] = p[1];
10595 if (mins[2] > p[2]) mins[2] = p[2];
10596 if (maxs[0] < p[0]) maxs[0] = p[0];
10597 if (maxs[1] < p[1]) maxs[1] = p[1];
10598 if (maxs[2] < p[2]) maxs[2] = p[2];
10602 VectorCopy(p, mins);
10603 VectorCopy(p, maxs);
10606 if (!R_ScissorForBBox(mins, maxs, scissor))
10610 if (skyscissor[0] > scissor[0])
10612 skyscissor[2] += skyscissor[0] - scissor[0];
10613 skyscissor[0] = scissor[0];
10615 if (skyscissor[1] > scissor[1])
10617 skyscissor[3] += skyscissor[1] - scissor[1];
10618 skyscissor[1] = scissor[1];
10620 if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10621 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10622 if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10623 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10626 Vector4Copy(scissor, skyscissor);
10631 // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10632 // skymasking on them, and Quake3 never did sky masking (unlike
10633 // software Quake and software Quake2), so disable the sky masking
10634 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10635 // and skymasking also looks very bad when noclipping outside the
10636 // level, so don't use it then either.
10637 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)
10639 R_Mesh_ResetTextureState();
10640 if (skyrendermasked)
10642 R_SetupShader_DepthOrShadow(false, false, false);
10643 // depth-only (masking)
10644 GL_ColorMask(0, 0, 0, 0);
10645 // just to make sure that braindead drivers don't draw
10646 // anything despite that colormask...
10647 GL_BlendFunc(GL_ZERO, GL_ONE);
10648 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10649 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10653 R_SetupShader_Generic_NoTexture(false, false);
10655 GL_BlendFunc(GL_ONE, GL_ZERO);
10656 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10657 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10658 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10661 if (skyrendermasked)
10662 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10664 R_Mesh_ResetTextureState();
10665 GL_Color(1, 1, 1, 1);
10668 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10669 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10670 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10672 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10676 // render screenspace normalmap to texture
10677 GL_DepthMask(true);
10678 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10683 // bind lightmap texture
10685 // water/refraction/reflection/camera surfaces have to be handled specially
10686 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10688 int start, end, startplaneindex;
10689 for (start = 0;start < texturenumsurfaces;start = end)
10691 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10692 if(startplaneindex < 0)
10694 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10695 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10699 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10701 // now that we have a batch using the same planeindex, render it
10702 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10704 // render water or distortion background
10705 GL_DepthMask(true);
10706 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10708 // blend surface on top
10709 GL_DepthMask(false);
10710 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10713 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10715 // render surface with reflection texture as input
10716 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10717 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10724 // render surface batch normally
10725 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10726 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10730 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10732 // OpenGL 1.3 path - anything not completely ancient
10733 qboolean applycolor;
10736 const texturelayer_t *layer;
10737 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);
10738 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10740 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10743 int layertexrgbscale;
10744 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10746 if (layerindex == 0)
10747 GL_AlphaTest(true);
10750 GL_AlphaTest(false);
10751 GL_DepthFunc(GL_EQUAL);
10754 GL_DepthMask(layer->depthmask && writedepth);
10755 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10756 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10758 layertexrgbscale = 4;
10759 VectorScale(layer->color, 0.25f, layercolor);
10761 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10763 layertexrgbscale = 2;
10764 VectorScale(layer->color, 0.5f, layercolor);
10768 layertexrgbscale = 1;
10769 VectorScale(layer->color, 1.0f, layercolor);
10771 layercolor[3] = layer->color[3];
10772 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10773 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10774 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10775 switch (layer->type)
10777 case TEXTURELAYERTYPE_LITTEXTURE:
10778 // single-pass lightmapped texture with 2x rgbscale
10779 R_Mesh_TexBind(0, r_texture_white);
10780 R_Mesh_TexMatrix(0, NULL);
10781 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10782 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10783 R_Mesh_TexBind(1, layer->texture);
10784 R_Mesh_TexMatrix(1, &layer->texmatrix);
10785 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10786 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10787 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10788 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10789 else if (FAKELIGHT_ENABLED)
10790 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10791 else if (rsurface.uselightmaptexture)
10792 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10794 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10796 case TEXTURELAYERTYPE_TEXTURE:
10797 // singletexture unlit texture with transparency support
10798 R_Mesh_TexBind(0, layer->texture);
10799 R_Mesh_TexMatrix(0, &layer->texmatrix);
10800 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10801 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10802 R_Mesh_TexBind(1, 0);
10803 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10804 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10806 case TEXTURELAYERTYPE_FOG:
10807 // singletexture fogging
10808 if (layer->texture)
10810 R_Mesh_TexBind(0, layer->texture);
10811 R_Mesh_TexMatrix(0, &layer->texmatrix);
10812 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10813 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10817 R_Mesh_TexBind(0, 0);
10818 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10820 R_Mesh_TexBind(1, 0);
10821 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10822 // generate a color array for the fog pass
10823 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10824 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10828 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10831 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10833 GL_DepthFunc(GL_LEQUAL);
10834 GL_AlphaTest(false);
10838 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10840 // OpenGL 1.1 - crusty old voodoo path
10843 const texturelayer_t *layer;
10844 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);
10845 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10847 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10849 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10851 if (layerindex == 0)
10852 GL_AlphaTest(true);
10855 GL_AlphaTest(false);
10856 GL_DepthFunc(GL_EQUAL);
10859 GL_DepthMask(layer->depthmask && writedepth);
10860 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10861 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10862 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10863 switch (layer->type)
10865 case TEXTURELAYERTYPE_LITTEXTURE:
10866 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10868 // two-pass lit texture with 2x rgbscale
10869 // first the lightmap pass
10870 R_Mesh_TexBind(0, r_texture_white);
10871 R_Mesh_TexMatrix(0, NULL);
10872 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10873 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10874 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10875 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10876 else if (FAKELIGHT_ENABLED)
10877 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10878 else if (rsurface.uselightmaptexture)
10879 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10881 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10882 // then apply the texture to it
10883 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10884 R_Mesh_TexBind(0, layer->texture);
10885 R_Mesh_TexMatrix(0, &layer->texmatrix);
10886 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10887 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10888 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);
10892 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10893 R_Mesh_TexBind(0, layer->texture);
10894 R_Mesh_TexMatrix(0, &layer->texmatrix);
10895 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10896 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10897 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10898 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);
10899 else if (FAKELIGHT_ENABLED)
10900 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);
10902 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);
10905 case TEXTURELAYERTYPE_TEXTURE:
10906 // singletexture unlit texture with transparency support
10907 R_Mesh_TexBind(0, layer->texture);
10908 R_Mesh_TexMatrix(0, &layer->texmatrix);
10909 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10910 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10911 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);
10913 case TEXTURELAYERTYPE_FOG:
10914 // singletexture fogging
10915 if (layer->texture)
10917 R_Mesh_TexBind(0, layer->texture);
10918 R_Mesh_TexMatrix(0, &layer->texmatrix);
10919 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10920 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10924 R_Mesh_TexBind(0, 0);
10925 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10927 // generate a color array for the fog pass
10928 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10929 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10933 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10936 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10938 GL_DepthFunc(GL_LEQUAL);
10939 GL_AlphaTest(false);
10943 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10947 r_vertexgeneric_t *batchvertex;
10949 texture_t *t = rsurface.texture;
10951 // R_Mesh_ResetTextureState();
10952 R_SetupShader_Generic_NoTexture(false, false);
10954 if(t && t->currentskinframe)
10956 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10957 c[3] *= t->currentalpha;
10967 if (t->pantstexture || t->shirttexture)
10969 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10970 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10971 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10974 // brighten it up (as texture value 127 means "unlit")
10975 c[0] *= 2 * r_refdef.view.colorscale;
10976 c[1] *= 2 * r_refdef.view.colorscale;
10977 c[2] *= 2 * r_refdef.view.colorscale;
10979 if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10980 c[3] *= r_wateralpha.value;
10982 if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10984 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10985 GL_DepthMask(false);
10987 else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10989 GL_BlendFunc(GL_ONE, GL_ONE);
10990 GL_DepthMask(false);
10992 else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10994 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10995 GL_DepthMask(false);
10997 else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10999 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
11000 GL_DepthMask(false);
11004 GL_BlendFunc(GL_ONE, GL_ZERO);
11005 GL_DepthMask(writedepth);
11008 if (r_showsurfaces.integer == 3)
11010 rsurface.passcolor4f = NULL;
11012 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11014 qboolean applycolor = true;
11017 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11019 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
11021 else if (FAKELIGHT_ENABLED)
11023 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11025 RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
11029 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11031 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11032 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11033 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11034 RSurf_DrawBatch_GL11_ApplyAmbient();
11037 if(!rsurface.passcolor4f)
11038 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11040 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11041 if(r_refdef.fogenabled)
11042 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11043 RSurf_DrawBatch_GL11_ClampColor();
11045 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11046 R_SetupShader_Generic_NoTexture(false, false);
11049 else if (!r_refdef.view.showdebug)
11051 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11053 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11055 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11056 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11058 R_Mesh_PrepareVertices_Generic_Unlock();
11061 else if (r_showsurfaces.integer == 4)
11063 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11064 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11065 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11067 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11068 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11069 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11071 R_Mesh_PrepareVertices_Generic_Unlock();
11074 else if (r_showsurfaces.integer == 2)
11077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11079 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11081 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11082 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11083 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11084 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11085 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11086 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11087 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11089 R_Mesh_PrepareVertices_Generic_Unlock();
11090 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11094 int texturesurfaceindex;
11096 const msurface_t *surface;
11097 float surfacecolor4f[4];
11098 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11099 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11101 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11103 surface = texturesurfacelist[texturesurfaceindex];
11104 k = (int)(((size_t)surface) / sizeof(msurface_t));
11105 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11106 for (j = 0;j < surface->num_vertices;j++)
11108 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11109 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11113 R_Mesh_PrepareVertices_Generic_Unlock();
11118 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11121 RSurf_SetupDepthAndCulling();
11122 if (r_showsurfaces.integer)
11124 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11127 switch (vid.renderpath)
11129 case RENDERPATH_GL20:
11130 case RENDERPATH_D3D9:
11131 case RENDERPATH_D3D10:
11132 case RENDERPATH_D3D11:
11133 case RENDERPATH_SOFT:
11134 case RENDERPATH_GLES2:
11135 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11137 case RENDERPATH_GL13:
11138 case RENDERPATH_GLES1:
11139 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11141 case RENDERPATH_GL11:
11142 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11148 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11151 int texturenumsurfaces, endsurface;
11152 texture_t *texture;
11153 const msurface_t *surface;
11154 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11156 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11157 RSurf_ActiveModelEntity(ent, false, false, false);
11160 switch (vid.renderpath)
11162 case RENDERPATH_GL20:
11163 case RENDERPATH_D3D9:
11164 case RENDERPATH_D3D10:
11165 case RENDERPATH_D3D11:
11166 case RENDERPATH_SOFT:
11167 case RENDERPATH_GLES2:
11168 RSurf_ActiveModelEntity(ent, true, true, false);
11170 case RENDERPATH_GL11:
11171 case RENDERPATH_GL13:
11172 case RENDERPATH_GLES1:
11173 RSurf_ActiveModelEntity(ent, true, false, false);
11178 if (r_transparentdepthmasking.integer)
11180 qboolean setup = false;
11181 for (i = 0;i < numsurfaces;i = j)
11184 surface = rsurface.modelsurfaces + surfacelist[i];
11185 texture = surface->texture;
11186 rsurface.texture = R_GetCurrentTexture(texture);
11187 rsurface.lightmaptexture = NULL;
11188 rsurface.deluxemaptexture = NULL;
11189 rsurface.uselightmaptexture = false;
11190 // scan ahead until we find a different texture
11191 endsurface = min(i + 1024, numsurfaces);
11192 texturenumsurfaces = 0;
11193 texturesurfacelist[texturenumsurfaces++] = surface;
11194 for (;j < endsurface;j++)
11196 surface = rsurface.modelsurfaces + surfacelist[j];
11197 if (texture != surface->texture)
11199 texturesurfacelist[texturenumsurfaces++] = surface;
11201 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11203 // render the range of surfaces as depth
11207 GL_ColorMask(0,0,0,0);
11209 GL_DepthTest(true);
11210 GL_BlendFunc(GL_ONE, GL_ZERO);
11211 GL_DepthMask(true);
11212 // R_Mesh_ResetTextureState();
11214 RSurf_SetupDepthAndCulling();
11215 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11216 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11217 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11221 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11224 for (i = 0;i < numsurfaces;i = j)
11227 surface = rsurface.modelsurfaces + surfacelist[i];
11228 texture = surface->texture;
11229 rsurface.texture = R_GetCurrentTexture(texture);
11230 // scan ahead until we find a different texture
11231 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11232 texturenumsurfaces = 0;
11233 texturesurfacelist[texturenumsurfaces++] = surface;
11234 if(FAKELIGHT_ENABLED)
11236 rsurface.lightmaptexture = NULL;
11237 rsurface.deluxemaptexture = NULL;
11238 rsurface.uselightmaptexture = false;
11239 for (;j < endsurface;j++)
11241 surface = rsurface.modelsurfaces + surfacelist[j];
11242 if (texture != surface->texture)
11244 texturesurfacelist[texturenumsurfaces++] = surface;
11249 rsurface.lightmaptexture = surface->lightmaptexture;
11250 rsurface.deluxemaptexture = surface->deluxemaptexture;
11251 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11252 for (;j < endsurface;j++)
11254 surface = rsurface.modelsurfaces + surfacelist[j];
11255 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11257 texturesurfacelist[texturenumsurfaces++] = surface;
11260 // render the range of surfaces
11261 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11263 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11266 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11268 // transparent surfaces get pushed off into the transparent queue
11269 int surfacelistindex;
11270 const msurface_t *surface;
11271 vec3_t tempcenter, center;
11272 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11274 surface = texturesurfacelist[surfacelistindex];
11275 if (r_transparent_sortsurfacesbynearest.integer)
11277 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11278 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11279 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11283 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11284 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11285 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11287 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11288 if (rsurface.entity->transparent_offset) // transparent offset
11290 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11291 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11292 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11294 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);
11298 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11300 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11302 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11304 RSurf_SetupDepthAndCulling();
11305 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11306 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11307 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11311 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11315 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11318 if (!rsurface.texture->currentnumlayers)
11320 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11321 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11323 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11325 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11326 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11327 else if (!rsurface.texture->currentnumlayers)
11329 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11331 // in the deferred case, transparent surfaces were queued during prepass
11332 if (!r_shadow_usingdeferredprepass)
11333 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11337 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11338 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11343 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11346 texture_t *texture;
11347 R_FrameData_SetMark();
11348 // break the surface list down into batches by texture and use of lightmapping
11349 for (i = 0;i < numsurfaces;i = j)
11352 // texture is the base texture pointer, rsurface.texture is the
11353 // current frame/skin the texture is directing us to use (for example
11354 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11355 // use skin 1 instead)
11356 texture = surfacelist[i]->texture;
11357 rsurface.texture = R_GetCurrentTexture(texture);
11358 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11360 // if this texture is not the kind we want, skip ahead to the next one
11361 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11365 if(FAKELIGHT_ENABLED || depthonly || prepass)
11367 rsurface.lightmaptexture = NULL;
11368 rsurface.deluxemaptexture = NULL;
11369 rsurface.uselightmaptexture = false;
11370 // simply scan ahead until we find a different texture or lightmap state
11371 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11376 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11377 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11378 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11379 // simply scan ahead until we find a different texture or lightmap state
11380 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11383 // render the range of surfaces
11384 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11386 R_FrameData_ReturnToMark();
11389 float locboxvertex3f[6*4*3] =
11391 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11392 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11393 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11394 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11395 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11396 1,0,0, 0,0,0, 0,1,0, 1,1,0
11399 unsigned short locboxelements[6*2*3] =
11404 12,13,14, 12,14,15,
11405 16,17,18, 16,18,19,
11409 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11412 cl_locnode_t *loc = (cl_locnode_t *)ent;
11414 float vertex3f[6*4*3];
11416 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11417 GL_DepthMask(false);
11418 GL_DepthRange(0, 1);
11419 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11420 GL_DepthTest(true);
11421 GL_CullFace(GL_NONE);
11422 R_EntityMatrix(&identitymatrix);
11424 // R_Mesh_ResetTextureState();
11426 i = surfacelist[0];
11427 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11428 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11429 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11430 surfacelist[0] < 0 ? 0.5f : 0.125f);
11432 if (VectorCompare(loc->mins, loc->maxs))
11434 VectorSet(size, 2, 2, 2);
11435 VectorMA(loc->mins, -0.5f, size, mins);
11439 VectorCopy(loc->mins, mins);
11440 VectorSubtract(loc->maxs, loc->mins, size);
11443 for (i = 0;i < 6*4*3;)
11444 for (j = 0;j < 3;j++, i++)
11445 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11447 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11448 R_SetupShader_Generic_NoTexture(false, false);
11449 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11452 void R_DrawLocs(void)
11455 cl_locnode_t *loc, *nearestloc;
11457 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11458 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11460 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11461 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11465 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11467 if (decalsystem->decals)
11468 Mem_Free(decalsystem->decals);
11469 memset(decalsystem, 0, sizeof(*decalsystem));
11472 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)
11475 tridecal_t *decals;
11478 // expand or initialize the system
11479 if (decalsystem->maxdecals <= decalsystem->numdecals)
11481 decalsystem_t old = *decalsystem;
11482 qboolean useshortelements;
11483 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11484 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11485 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)));
11486 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11487 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11488 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11489 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11490 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11491 if (decalsystem->numdecals)
11492 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11494 Mem_Free(old.decals);
11495 for (i = 0;i < decalsystem->maxdecals*3;i++)
11496 decalsystem->element3i[i] = i;
11497 if (useshortelements)
11498 for (i = 0;i < decalsystem->maxdecals*3;i++)
11499 decalsystem->element3s[i] = i;
11502 // grab a decal and search for another free slot for the next one
11503 decals = decalsystem->decals;
11504 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11505 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11507 decalsystem->freedecal = i;
11508 if (decalsystem->numdecals <= i)
11509 decalsystem->numdecals = i + 1;
11511 // initialize the decal
11513 decal->triangleindex = triangleindex;
11514 decal->surfaceindex = surfaceindex;
11515 decal->decalsequence = decalsequence;
11516 decal->color4f[0][0] = c0[0];
11517 decal->color4f[0][1] = c0[1];
11518 decal->color4f[0][2] = c0[2];
11519 decal->color4f[0][3] = 1;
11520 decal->color4f[1][0] = c1[0];
11521 decal->color4f[1][1] = c1[1];
11522 decal->color4f[1][2] = c1[2];
11523 decal->color4f[1][3] = 1;
11524 decal->color4f[2][0] = c2[0];
11525 decal->color4f[2][1] = c2[1];
11526 decal->color4f[2][2] = c2[2];
11527 decal->color4f[2][3] = 1;
11528 decal->vertex3f[0][0] = v0[0];
11529 decal->vertex3f[0][1] = v0[1];
11530 decal->vertex3f[0][2] = v0[2];
11531 decal->vertex3f[1][0] = v1[0];
11532 decal->vertex3f[1][1] = v1[1];
11533 decal->vertex3f[1][2] = v1[2];
11534 decal->vertex3f[2][0] = v2[0];
11535 decal->vertex3f[2][1] = v2[1];
11536 decal->vertex3f[2][2] = v2[2];
11537 decal->texcoord2f[0][0] = t0[0];
11538 decal->texcoord2f[0][1] = t0[1];
11539 decal->texcoord2f[1][0] = t1[0];
11540 decal->texcoord2f[1][1] = t1[1];
11541 decal->texcoord2f[2][0] = t2[0];
11542 decal->texcoord2f[2][1] = t2[1];
11543 TriangleNormal(v0, v1, v2, decal->plane);
11544 VectorNormalize(decal->plane);
11545 decal->plane[3] = DotProduct(v0, decal->plane);
11548 extern cvar_t cl_decals_bias;
11549 extern cvar_t cl_decals_models;
11550 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11551 // baseparms, parms, temps
11552 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)
11557 const float *vertex3f;
11558 const float *normal3f;
11560 float points[2][9][3];
11567 e = rsurface.modelelement3i + 3*triangleindex;
11569 vertex3f = rsurface.modelvertex3f;
11570 normal3f = rsurface.modelnormal3f;
11574 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11576 index = 3*e[cornerindex];
11577 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11582 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11584 index = 3*e[cornerindex];
11585 VectorCopy(vertex3f + index, v[cornerindex]);
11590 //TriangleNormal(v[0], v[1], v[2], normal);
11591 //if (DotProduct(normal, localnormal) < 0.0f)
11593 // clip by each of the box planes formed from the projection matrix
11594 // if anything survives, we emit the decal
11595 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]);
11598 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]);
11601 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]);
11604 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]);
11607 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]);
11610 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]);
11613 // some part of the triangle survived, so we have to accept it...
11616 // dynamic always uses the original triangle
11618 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11620 index = 3*e[cornerindex];
11621 VectorCopy(vertex3f + index, v[cornerindex]);
11624 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11626 // convert vertex positions to texcoords
11627 Matrix4x4_Transform(projection, v[cornerindex], temp);
11628 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11629 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11630 // calculate distance fade from the projection origin
11631 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11632 f = bound(0.0f, f, 1.0f);
11633 c[cornerindex][0] = r * f;
11634 c[cornerindex][1] = g * f;
11635 c[cornerindex][2] = b * f;
11636 c[cornerindex][3] = 1.0f;
11637 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11640 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);
11642 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11643 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);
11645 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)
11647 matrix4x4_t projection;
11648 decalsystem_t *decalsystem;
11651 const msurface_t *surface;
11652 const msurface_t *surfaces;
11653 const int *surfacelist;
11654 const texture_t *texture;
11656 int numsurfacelist;
11657 int surfacelistindex;
11660 float localorigin[3];
11661 float localnormal[3];
11662 float localmins[3];
11663 float localmaxs[3];
11666 float planes[6][4];
11669 int bih_triangles_count;
11670 int bih_triangles[256];
11671 int bih_surfaces[256];
11673 decalsystem = &ent->decalsystem;
11674 model = ent->model;
11675 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11677 R_DecalSystem_Reset(&ent->decalsystem);
11681 if (!model->brush.data_leafs && !cl_decals_models.integer)
11683 if (decalsystem->model)
11684 R_DecalSystem_Reset(decalsystem);
11688 if (decalsystem->model != model)
11689 R_DecalSystem_Reset(decalsystem);
11690 decalsystem->model = model;
11692 RSurf_ActiveModelEntity(ent, true, false, false);
11694 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11695 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11696 VectorNormalize(localnormal);
11697 localsize = worldsize*rsurface.inversematrixscale;
11698 localmins[0] = localorigin[0] - localsize;
11699 localmins[1] = localorigin[1] - localsize;
11700 localmins[2] = localorigin[2] - localsize;
11701 localmaxs[0] = localorigin[0] + localsize;
11702 localmaxs[1] = localorigin[1] + localsize;
11703 localmaxs[2] = localorigin[2] + localsize;
11705 //VectorCopy(localnormal, planes[4]);
11706 //VectorVectors(planes[4], planes[2], planes[0]);
11707 AnglesFromVectors(angles, localnormal, NULL, false);
11708 AngleVectors(angles, planes[0], planes[2], planes[4]);
11709 VectorNegate(planes[0], planes[1]);
11710 VectorNegate(planes[2], planes[3]);
11711 VectorNegate(planes[4], planes[5]);
11712 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11713 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11714 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11715 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11716 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11717 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11722 matrix4x4_t forwardprojection;
11723 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11724 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11729 float projectionvector[4][3];
11730 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11731 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11732 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11733 projectionvector[0][0] = planes[0][0] * ilocalsize;
11734 projectionvector[0][1] = planes[1][0] * ilocalsize;
11735 projectionvector[0][2] = planes[2][0] * ilocalsize;
11736 projectionvector[1][0] = planes[0][1] * ilocalsize;
11737 projectionvector[1][1] = planes[1][1] * ilocalsize;
11738 projectionvector[1][2] = planes[2][1] * ilocalsize;
11739 projectionvector[2][0] = planes[0][2] * ilocalsize;
11740 projectionvector[2][1] = planes[1][2] * ilocalsize;
11741 projectionvector[2][2] = planes[2][2] * ilocalsize;
11742 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11743 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11744 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11745 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11749 dynamic = model->surfmesh.isanimated;
11750 numsurfacelist = model->nummodelsurfaces;
11751 surfacelist = model->sortedmodelsurfaces;
11752 surfaces = model->data_surfaces;
11755 bih_triangles_count = -1;
11758 if(model->render_bih.numleafs)
11759 bih = &model->render_bih;
11760 else if(model->collision_bih.numleafs)
11761 bih = &model->collision_bih;
11764 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11765 if(bih_triangles_count == 0)
11767 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11769 if(bih_triangles_count > 0)
11771 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11773 surfaceindex = bih_surfaces[triangleindex];
11774 surface = surfaces + surfaceindex;
11775 texture = surface->texture;
11776 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11778 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11780 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11785 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11787 surfaceindex = surfacelist[surfacelistindex];
11788 surface = surfaces + surfaceindex;
11789 // check cull box first because it rejects more than any other check
11790 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11792 // skip transparent surfaces
11793 texture = surface->texture;
11794 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11796 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11798 numtriangles = surface->num_triangles;
11799 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11800 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11805 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11806 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)
11808 int renderentityindex;
11809 float worldmins[3];
11810 float worldmaxs[3];
11811 entity_render_t *ent;
11813 if (!cl_decals_newsystem.integer)
11816 worldmins[0] = worldorigin[0] - worldsize;
11817 worldmins[1] = worldorigin[1] - worldsize;
11818 worldmins[2] = worldorigin[2] - worldsize;
11819 worldmaxs[0] = worldorigin[0] + worldsize;
11820 worldmaxs[1] = worldorigin[1] + worldsize;
11821 worldmaxs[2] = worldorigin[2] + worldsize;
11823 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11825 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11827 ent = r_refdef.scene.entities[renderentityindex];
11828 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11831 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11835 typedef struct r_decalsystem_splatqueue_s
11837 vec3_t worldorigin;
11838 vec3_t worldnormal;
11842 unsigned int decalsequence;
11844 r_decalsystem_splatqueue_t;
11846 int r_decalsystem_numqueued = 0;
11847 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11849 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)
11851 r_decalsystem_splatqueue_t *queue;
11853 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11856 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11857 VectorCopy(worldorigin, queue->worldorigin);
11858 VectorCopy(worldnormal, queue->worldnormal);
11859 Vector4Set(queue->color, r, g, b, a);
11860 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11861 queue->worldsize = worldsize;
11862 queue->decalsequence = cl.decalsequence++;
11865 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11868 r_decalsystem_splatqueue_t *queue;
11870 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11871 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);
11872 r_decalsystem_numqueued = 0;
11875 extern cvar_t cl_decals_max;
11876 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11879 decalsystem_t *decalsystem = &ent->decalsystem;
11881 unsigned int killsequence;
11886 if (!decalsystem->numdecals)
11889 if (r_showsurfaces.integer)
11892 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11894 R_DecalSystem_Reset(decalsystem);
11898 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11899 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11901 if (decalsystem->lastupdatetime)
11902 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11905 decalsystem->lastupdatetime = r_refdef.scene.time;
11906 numdecals = decalsystem->numdecals;
11908 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11910 if (decal->color4f[0][3])
11912 decal->lived += frametime;
11913 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11915 memset(decal, 0, sizeof(*decal));
11916 if (decalsystem->freedecal > i)
11917 decalsystem->freedecal = i;
11921 decal = decalsystem->decals;
11922 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11925 // collapse the array by shuffling the tail decals into the gaps
11928 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11929 decalsystem->freedecal++;
11930 if (decalsystem->freedecal == numdecals)
11932 decal[decalsystem->freedecal] = decal[--numdecals];
11935 decalsystem->numdecals = numdecals;
11937 if (numdecals <= 0)
11939 // if there are no decals left, reset decalsystem
11940 R_DecalSystem_Reset(decalsystem);
11944 extern skinframe_t *decalskinframe;
11945 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11948 decalsystem_t *decalsystem = &ent->decalsystem;
11957 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11960 numdecals = decalsystem->numdecals;
11964 if (r_showsurfaces.integer)
11967 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11969 R_DecalSystem_Reset(decalsystem);
11973 // if the model is static it doesn't matter what value we give for
11974 // wantnormals and wanttangents, so this logic uses only rules applicable
11975 // to a model, knowing that they are meaningless otherwise
11976 RSurf_ActiveModelEntity(ent, false, false, false);
11978 decalsystem->lastupdatetime = r_refdef.scene.time;
11980 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11982 // update vertex positions for animated models
11983 v3f = decalsystem->vertex3f;
11984 c4f = decalsystem->color4f;
11985 t2f = decalsystem->texcoord2f;
11986 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11988 if (!decal->color4f[0][3])
11991 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11995 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11998 // update color values for fading decals
11999 if (decal->lived >= cl_decals_time.value)
12000 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12004 c4f[ 0] = decal->color4f[0][0] * alpha;
12005 c4f[ 1] = decal->color4f[0][1] * alpha;
12006 c4f[ 2] = decal->color4f[0][2] * alpha;
12008 c4f[ 4] = decal->color4f[1][0] * alpha;
12009 c4f[ 5] = decal->color4f[1][1] * alpha;
12010 c4f[ 6] = decal->color4f[1][2] * alpha;
12012 c4f[ 8] = decal->color4f[2][0] * alpha;
12013 c4f[ 9] = decal->color4f[2][1] * alpha;
12014 c4f[10] = decal->color4f[2][2] * alpha;
12017 t2f[0] = decal->texcoord2f[0][0];
12018 t2f[1] = decal->texcoord2f[0][1];
12019 t2f[2] = decal->texcoord2f[1][0];
12020 t2f[3] = decal->texcoord2f[1][1];
12021 t2f[4] = decal->texcoord2f[2][0];
12022 t2f[5] = decal->texcoord2f[2][1];
12024 // update vertex positions for animated models
12025 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12027 e = rsurface.modelelement3i + 3*decal->triangleindex;
12028 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12029 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12030 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12034 VectorCopy(decal->vertex3f[0], v3f);
12035 VectorCopy(decal->vertex3f[1], v3f + 3);
12036 VectorCopy(decal->vertex3f[2], v3f + 6);
12039 if (r_refdef.fogenabled)
12041 alpha = RSurf_FogVertex(v3f);
12042 VectorScale(c4f, alpha, c4f);
12043 alpha = RSurf_FogVertex(v3f + 3);
12044 VectorScale(c4f + 4, alpha, c4f + 4);
12045 alpha = RSurf_FogVertex(v3f + 6);
12046 VectorScale(c4f + 8, alpha, c4f + 8);
12057 r_refdef.stats[r_stat_drawndecals] += numtris;
12059 // now render the decals all at once
12060 // (this assumes they all use one particle font texture!)
12061 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);
12062 // R_Mesh_ResetTextureState();
12063 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12064 GL_DepthMask(false);
12065 GL_DepthRange(0, 1);
12066 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12067 GL_DepthTest(true);
12068 GL_CullFace(GL_NONE);
12069 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12070 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12071 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12075 static void R_DrawModelDecals(void)
12079 // fade faster when there are too many decals
12080 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12081 for (i = 0;i < r_refdef.scene.numentities;i++)
12082 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12084 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12085 for (i = 0;i < r_refdef.scene.numentities;i++)
12086 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12087 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12089 R_DecalSystem_ApplySplatEntitiesQueue();
12091 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12092 for (i = 0;i < r_refdef.scene.numentities;i++)
12093 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12095 r_refdef.stats[r_stat_totaldecals] += numdecals;
12097 if (r_showsurfaces.integer)
12100 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12102 for (i = 0;i < r_refdef.scene.numentities;i++)
12104 if (!r_refdef.viewcache.entityvisible[i])
12106 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12107 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12111 extern cvar_t mod_collision_bih;
12112 static void R_DrawDebugModel(void)
12114 entity_render_t *ent = rsurface.entity;
12115 int i, j, flagsmask;
12116 const msurface_t *surface;
12117 dp_model_t *model = ent->model;
12119 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12122 if (r_showoverdraw.value > 0)
12124 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12125 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12126 R_SetupShader_Generic_NoTexture(false, false);
12127 GL_DepthTest(false);
12128 GL_DepthMask(false);
12129 GL_DepthRange(0, 1);
12130 GL_BlendFunc(GL_ONE, GL_ONE);
12131 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12133 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12135 rsurface.texture = R_GetCurrentTexture(surface->texture);
12136 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12138 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12139 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12140 if (!rsurface.texture->currentlayers->depthmask)
12141 GL_Color(c, 0, 0, 1.0f);
12142 else if (ent == r_refdef.scene.worldentity)
12143 GL_Color(c, c, c, 1.0f);
12145 GL_Color(0, c, 0, 1.0f);
12146 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12150 rsurface.texture = NULL;
12153 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12155 // R_Mesh_ResetTextureState();
12156 R_SetupShader_Generic_NoTexture(false, false);
12157 GL_DepthRange(0, 1);
12158 GL_DepthTest(!r_showdisabledepthtest.integer);
12159 GL_DepthMask(false);
12160 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12162 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12166 qboolean cullbox = false;
12167 const q3mbrush_t *brush;
12168 const bih_t *bih = &model->collision_bih;
12169 const bih_leaf_t *bihleaf;
12170 float vertex3f[3][3];
12171 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12172 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12174 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12176 switch (bihleaf->type)
12179 brush = model->brush.data_brushes + bihleaf->itemindex;
12180 if (brush->colbrushf && brush->colbrushf->numtriangles)
12182 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);
12183 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12184 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12187 case BIH_COLLISIONTRIANGLE:
12188 triangleindex = bihleaf->itemindex;
12189 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12190 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12191 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12192 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);
12193 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12194 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12196 case BIH_RENDERTRIANGLE:
12197 triangleindex = bihleaf->itemindex;
12198 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12199 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12200 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12201 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);
12202 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12203 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12209 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12212 if (r_showtris.integer && qglPolygonMode)
12214 if (r_showdisabledepthtest.integer)
12216 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12217 GL_DepthMask(false);
12221 GL_BlendFunc(GL_ONE, GL_ZERO);
12222 GL_DepthMask(true);
12224 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12225 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12227 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12229 rsurface.texture = R_GetCurrentTexture(surface->texture);
12230 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12232 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12233 if (!rsurface.texture->currentlayers->depthmask)
12234 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12235 else if (ent == r_refdef.scene.worldentity)
12236 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12238 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12239 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12243 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12244 rsurface.texture = NULL;
12247 if (r_shownormals.value != 0 && qglBegin)
12251 if (r_showdisabledepthtest.integer)
12253 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12254 GL_DepthMask(false);
12258 GL_BlendFunc(GL_ONE, GL_ZERO);
12259 GL_DepthMask(true);
12261 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12263 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12265 rsurface.texture = R_GetCurrentTexture(surface->texture);
12266 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12268 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12269 qglBegin(GL_LINES);
12270 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12272 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12274 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12275 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12276 qglVertex3f(v[0], v[1], v[2]);
12277 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12278 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12279 qglVertex3f(v[0], v[1], v[2]);
12282 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12284 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12286 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12287 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12288 qglVertex3f(v[0], v[1], v[2]);
12289 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12290 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12291 qglVertex3f(v[0], v[1], v[2]);
12294 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12296 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12298 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12299 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12300 qglVertex3f(v[0], v[1], v[2]);
12301 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12302 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12303 qglVertex3f(v[0], v[1], v[2]);
12306 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12308 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12310 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12311 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12312 qglVertex3f(v[0], v[1], v[2]);
12313 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12314 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12315 qglVertex3f(v[0], v[1], v[2]);
12322 rsurface.texture = NULL;
12327 int r_maxsurfacelist = 0;
12328 const msurface_t **r_surfacelist = NULL;
12329 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12331 int i, j, endj, flagsmask;
12332 dp_model_t *model = ent->model;
12333 msurface_t *surfaces;
12334 unsigned char *update;
12335 int numsurfacelist = 0;
12339 if (r_maxsurfacelist < model->num_surfaces)
12341 r_maxsurfacelist = model->num_surfaces;
12343 Mem_Free((msurface_t **)r_surfacelist);
12344 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12347 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12348 RSurf_ActiveModelEntity(ent, false, false, false);
12350 RSurf_ActiveModelEntity(ent, true, true, true);
12351 else if (depthonly)
12353 switch (vid.renderpath)
12355 case RENDERPATH_GL20:
12356 case RENDERPATH_D3D9:
12357 case RENDERPATH_D3D10:
12358 case RENDERPATH_D3D11:
12359 case RENDERPATH_SOFT:
12360 case RENDERPATH_GLES2:
12361 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12363 case RENDERPATH_GL11:
12364 case RENDERPATH_GL13:
12365 case RENDERPATH_GLES1:
12366 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12372 switch (vid.renderpath)
12374 case RENDERPATH_GL20:
12375 case RENDERPATH_D3D9:
12376 case RENDERPATH_D3D10:
12377 case RENDERPATH_D3D11:
12378 case RENDERPATH_SOFT:
12379 case RENDERPATH_GLES2:
12380 RSurf_ActiveModelEntity(ent, true, true, false);
12382 case RENDERPATH_GL11:
12383 case RENDERPATH_GL13:
12384 case RENDERPATH_GLES1:
12385 RSurf_ActiveModelEntity(ent, true, false, false);
12390 surfaces = model->data_surfaces;
12391 update = model->brushq1.lightmapupdateflags;
12393 // update light styles
12394 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12396 model_brush_lightstyleinfo_t *style;
12397 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12399 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12401 int *list = style->surfacelist;
12402 style->value = r_refdef.scene.lightstylevalue[style->style];
12403 for (j = 0;j < style->numsurfaces;j++)
12404 update[list[j]] = true;
12409 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12413 R_DrawDebugModel();
12414 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12418 rsurface.lightmaptexture = NULL;
12419 rsurface.deluxemaptexture = NULL;
12420 rsurface.uselightmaptexture = false;
12421 rsurface.texture = NULL;
12422 rsurface.rtlight = NULL;
12423 numsurfacelist = 0;
12424 // add visible surfaces to draw list
12425 if (ent == r_refdef.scene.worldentity)
12427 // for the world entity, check surfacevisible
12428 for (i = 0;i < model->nummodelsurfaces;i++)
12430 j = model->sortedmodelsurfaces[i];
12431 if (r_refdef.viewcache.world_surfacevisible[j])
12432 r_surfacelist[numsurfacelist++] = surfaces + j;
12437 // add all surfaces
12438 for (i = 0; i < model->nummodelsurfaces; i++)
12439 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12441 // don't do anything if there were no surfaces
12442 if (!numsurfacelist)
12444 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12447 // update lightmaps if needed
12451 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12456 R_BuildLightMap(ent, surfaces + j);
12461 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12463 // add to stats if desired
12464 if (r_speeds.integer && !skysurfaces && !depthonly)
12466 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12467 for (j = 0;j < numsurfacelist;j++)
12468 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12471 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12474 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12477 static texture_t texture;
12478 static msurface_t surface;
12479 const msurface_t *surfacelist = &surface;
12481 // fake enough texture and surface state to render this geometry
12483 texture.update_lastrenderframe = -1; // regenerate this texture
12484 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12485 texture.basealpha = 1.0f;
12486 texture.currentskinframe = skinframe;
12487 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12488 texture.offsetmapping = OFFSETMAPPING_OFF;
12489 texture.offsetscale = 1;
12490 texture.specularscalemod = 1;
12491 texture.specularpowermod = 1;
12492 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12493 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12494 // JUST GREP FOR "specularscalemod = 1".
12496 for (q = 0; q < 3; q++)
12498 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12499 texture.render_modellight_lightdir[q] = q == 2;
12500 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12501 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12502 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12503 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12504 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12505 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12506 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12507 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12509 texture.currentalpha = 1.0f;
12511 surface.texture = &texture;
12512 surface.num_triangles = numtriangles;
12513 surface.num_firsttriangle = firsttriangle;
12514 surface.num_vertices = numvertices;
12515 surface.num_firstvertex = firstvertex;
12518 rsurface.texture = R_GetCurrentTexture(surface.texture);
12519 rsurface.lightmaptexture = NULL;
12520 rsurface.deluxemaptexture = NULL;
12521 rsurface.uselightmaptexture = false;
12522 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12525 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)
12527 static msurface_t surface;
12528 const msurface_t *surfacelist = &surface;
12530 // fake enough texture and surface state to render this geometry
12531 surface.texture = texture;
12532 surface.num_triangles = numtriangles;
12533 surface.num_firsttriangle = firsttriangle;
12534 surface.num_vertices = numvertices;
12535 surface.num_firstvertex = firstvertex;
12538 rsurface.texture = R_GetCurrentTexture(surface.texture);
12539 rsurface.lightmaptexture = NULL;
12540 rsurface.deluxemaptexture = NULL;
12541 rsurface.uselightmaptexture = false;
12542 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);