2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
31 #include "cl_collision.h"
35 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
39 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
43 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
49 mempool_t *r_main_mempool;
50 rtexturepool_t *r_main_texturepool;
52 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
54 static qboolean r_loadnormalmap;
55 static qboolean r_loadgloss;
57 static qboolean r_loaddds;
58 static qboolean r_savedds;
59 static qboolean r_gpuskeletal;
66 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
68 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
69 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
70 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
71 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
72 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
73 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
74 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
75 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
76 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
77 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
79 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
80 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
82 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
85 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
86 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
87 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
88 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
89 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
90 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
91 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
92 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
93 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
94 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
95 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
96 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
97 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
98 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
99 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
100 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
101 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
103 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
104 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
105 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
106 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
107 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
108 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
109 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
110 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
111 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
112 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
113 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
114 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
115 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
116 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
117 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
118 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
119 cvar_t r_cullentities_trace_eyejitter = {0, "r_cullentities_trace_eyejitter", "16", "randomly offset rays from the eye by this much to reduce the odds of flickering"};
120 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
121 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
122 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
124 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
126 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
128 cvar_t r_fullbright_directed = {0, "r_fullbright_directed", "0", "render fullbright things (unlit worldmodel and EF_FULLBRIGHT entities, but not fullbright shaders) using a constant light direction instead to add more depth while keeping uniform brightness"};
129 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
130 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
131 cvar_t r_fullbright_directed_pitch = {0, "r_fullbright_directed_pitch", "20", "constant pitch direction ('height') of the fake light source to use for fullbright"};
132 cvar_t r_fullbright_directed_pitch_relative = {0, "r_fullbright_directed_pitch_relative", "0", "whether r_fullbright_directed_pitch is interpreted as absolute (0) or relative (1) pitch"};
134 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
135 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
136 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
137 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
138 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
139 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
140 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
141 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
142 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
143 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
144 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
145 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
146 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
147 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
148 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
149 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
150 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
152 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
153 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
154 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
155 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
156 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
157 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
158 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
159 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
161 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
162 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
163 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
164 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
165 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
166 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
167 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
168 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
170 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
171 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
173 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
174 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
175 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
177 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
178 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
179 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
180 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
181 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
182 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
183 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
184 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
185 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
187 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
188 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
189 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
190 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
191 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
192 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
193 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
194 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
195 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
196 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
197 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
198 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
199 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
200 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
201 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
202 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
203 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
204 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
205 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
207 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
208 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
209 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
210 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
211 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
212 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
213 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
214 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
215 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
216 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
218 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
219 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
220 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
221 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
223 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
224 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
226 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
227 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
228 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
229 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
230 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
231 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
233 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
234 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
235 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
236 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
237 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
238 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
240 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
241 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
242 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
244 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
246 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
248 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
250 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
252 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
253 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
254 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
255 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
257 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
258 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
260 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
262 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
263 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
265 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
266 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
267 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
268 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
271 extern cvar_t v_glslgamma;
272 extern cvar_t v_glslgamma_2d;
274 extern qboolean v_flipped_state;
276 r_framebufferstate_t r_fb;
278 /// shadow volume bsp struct with automatically growing nodes buffer
281 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
283 rtexture_t *r_texture_blanknormalmap;
284 rtexture_t *r_texture_white;
285 rtexture_t *r_texture_grey128;
286 rtexture_t *r_texture_black;
287 rtexture_t *r_texture_notexture;
288 rtexture_t *r_texture_whitecube;
289 rtexture_t *r_texture_normalizationcube;
290 rtexture_t *r_texture_fogattenuation;
291 rtexture_t *r_texture_fogheighttexture;
292 rtexture_t *r_texture_gammaramps;
293 unsigned int r_texture_gammaramps_serial;
294 //rtexture_t *r_texture_fogintensity;
295 rtexture_t *r_texture_reflectcube;
297 // TODO: hash lookups?
298 typedef struct cubemapinfo_s
305 int r_texture_numcubemaps;
306 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
308 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
309 unsigned int r_numqueries;
310 unsigned int r_maxqueries;
312 typedef struct r_qwskincache_s
314 char name[MAX_QPATH];
315 skinframe_t *skinframe;
319 static r_qwskincache_t *r_qwskincache;
320 static int r_qwskincache_size;
322 /// vertex coordinates for a quad that covers the screen exactly
323 extern const float r_screenvertex3f[12];
324 extern const float r_d3dscreenvertex3f[12];
325 const float r_screenvertex3f[12] =
332 const float r_d3dscreenvertex3f[12] =
340 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
343 for (i = 0;i < verts;i++)
354 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
357 for (i = 0;i < verts;i++)
367 // FIXME: move this to client?
370 if (gamemode == GAME_NEHAHRA)
372 Cvar_Set("gl_fogenable", "0");
373 Cvar_Set("gl_fogdensity", "0.2");
374 Cvar_Set("gl_fogred", "0.3");
375 Cvar_Set("gl_foggreen", "0.3");
376 Cvar_Set("gl_fogblue", "0.3");
378 r_refdef.fog_density = 0;
379 r_refdef.fog_red = 0;
380 r_refdef.fog_green = 0;
381 r_refdef.fog_blue = 0;
382 r_refdef.fog_alpha = 1;
383 r_refdef.fog_start = 0;
384 r_refdef.fog_end = 16384;
385 r_refdef.fog_height = 1<<30;
386 r_refdef.fog_fadedepth = 128;
387 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
390 static void R_BuildBlankTextures(void)
392 unsigned char data[4];
393 data[2] = 128; // normal X
394 data[1] = 128; // normal Y
395 data[0] = 255; // normal Z
396 data[3] = 255; // height
397 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
402 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
412 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
415 static void R_BuildNoTexture(void)
418 unsigned char pix[16][16][4];
419 // this makes a light grey/dark grey checkerboard texture
420 for (y = 0;y < 16;y++)
422 for (x = 0;x < 16;x++)
424 if ((y < 8) ^ (x < 8))
440 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
443 static void R_BuildWhiteCube(void)
445 unsigned char data[6*1*1*4];
446 memset(data, 255, sizeof(data));
447 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
450 static void R_BuildNormalizationCube(void)
454 vec_t s, t, intensity;
457 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
458 for (side = 0;side < 6;side++)
460 for (y = 0;y < NORMSIZE;y++)
462 for (x = 0;x < NORMSIZE;x++)
464 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
465 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
500 intensity = 127.0f / sqrt(DotProduct(v, v));
501 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
502 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
503 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
504 data[((side*64+y)*64+x)*4+3] = 255;
508 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
512 static void R_BuildFogTexture(void)
516 unsigned char data1[FOGWIDTH][4];
517 //unsigned char data2[FOGWIDTH][4];
520 r_refdef.fogmasktable_start = r_refdef.fog_start;
521 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
522 r_refdef.fogmasktable_range = r_refdef.fogrange;
523 r_refdef.fogmasktable_density = r_refdef.fog_density;
525 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
526 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
528 d = (x * r - r_refdef.fogmasktable_start);
529 if(developer_extra.integer)
530 Con_DPrintf("%f ", d);
532 if (r_fog_exp2.integer)
533 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
535 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
536 if(developer_extra.integer)
537 Con_DPrintf(" : %f ", alpha);
538 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
539 if(developer_extra.integer)
540 Con_DPrintf(" = %f\n", alpha);
541 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
544 for (x = 0;x < FOGWIDTH;x++)
546 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
551 //data2[x][0] = 255 - b;
552 //data2[x][1] = 255 - b;
553 //data2[x][2] = 255 - b;
556 if (r_texture_fogattenuation)
558 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
559 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
563 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
564 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
568 static void R_BuildFogHeightTexture(void)
570 unsigned char *inpixels;
578 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
579 if (r_refdef.fogheighttexturename[0])
580 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
583 r_refdef.fog_height_tablesize = 0;
584 if (r_texture_fogheighttexture)
585 R_FreeTexture(r_texture_fogheighttexture);
586 r_texture_fogheighttexture = NULL;
587 if (r_refdef.fog_height_table2d)
588 Mem_Free(r_refdef.fog_height_table2d);
589 r_refdef.fog_height_table2d = NULL;
590 if (r_refdef.fog_height_table1d)
591 Mem_Free(r_refdef.fog_height_table1d);
592 r_refdef.fog_height_table1d = NULL;
596 r_refdef.fog_height_tablesize = size;
597 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
598 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
599 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
601 // LordHavoc: now the magic - what is that table2d for? it is a cooked
602 // average fog color table accounting for every fog layer between a point
603 // and the camera. (Note: attenuation is handled separately!)
604 for (y = 0;y < size;y++)
606 for (x = 0;x < size;x++)
612 for (j = x;j <= y;j++)
614 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
620 for (j = x;j >= y;j--)
622 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
627 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
628 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
629 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
630 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
633 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
636 //=======================================================================================================================================================
638 static const char *builtinshaderstrings[] =
640 #include "shader_glsl.h"
644 const char *builtinhlslshaderstrings[] =
646 #include "shader_hlsl.h"
650 //=======================================================================================================================================================
652 typedef struct shaderpermutationinfo_s
657 shaderpermutationinfo_t;
659 typedef struct shadermodeinfo_s
661 const char *sourcebasename;
662 const char *extension;
663 const char **builtinshaderstrings;
672 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
673 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
675 {"#define USEDIFFUSE\n", " diffuse"},
676 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
677 {"#define USEVIEWTINT\n", " viewtint"},
678 {"#define USECOLORMAPPING\n", " colormapping"},
679 {"#define USESATURATION\n", " saturation"},
680 {"#define USEFOGINSIDE\n", " foginside"},
681 {"#define USEFOGOUTSIDE\n", " fogoutside"},
682 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
683 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
684 {"#define USEGAMMARAMPS\n", " gammaramps"},
685 {"#define USECUBEFILTER\n", " cubefilter"},
686 {"#define USEGLOW\n", " glow"},
687 {"#define USEBLOOM\n", " bloom"},
688 {"#define USESPECULAR\n", " specular"},
689 {"#define USEPOSTPROCESSING\n", " postprocessing"},
690 {"#define USEREFLECTION\n", " reflection"},
691 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
692 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
693 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
694 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
695 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
696 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
697 {"#define USEALPHAKILL\n", " alphakill"},
698 {"#define USEREFLECTCUBE\n", " reflectcube"},
699 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
700 {"#define USEBOUNCEGRID\n", " bouncegrid"},
701 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
702 {"#define USETRIPPY\n", " trippy"},
703 {"#define USEDEPTHRGB\n", " depthrgb"},
704 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
705 {"#define USESKELETAL\n", " skeletal"},
706 {"#define USEOCCLUDE\n", " occlude"}
709 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
710 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
712 // SHADERLANGUAGE_GLSL
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
721 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
722 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
723 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
724 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
725 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
726 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
727 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
728 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
729 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
730 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
732 // SHADERLANGUAGE_HLSL
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
741 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
742 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
743 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
744 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
745 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
746 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
747 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
748 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
749 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
750 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
754 struct r_glsl_permutation_s;
755 typedef struct r_glsl_permutation_s
758 struct r_glsl_permutation_s *hashnext;
760 dpuint64 permutation;
762 /// indicates if we have tried compiling this permutation already
764 /// 0 if compilation failed
766 // texture units assigned to each detected uniform
767 int tex_Texture_First;
768 int tex_Texture_Second;
769 int tex_Texture_GammaRamps;
770 int tex_Texture_Normal;
771 int tex_Texture_Color;
772 int tex_Texture_Gloss;
773 int tex_Texture_Glow;
774 int tex_Texture_SecondaryNormal;
775 int tex_Texture_SecondaryColor;
776 int tex_Texture_SecondaryGloss;
777 int tex_Texture_SecondaryGlow;
778 int tex_Texture_Pants;
779 int tex_Texture_Shirt;
780 int tex_Texture_FogHeightTexture;
781 int tex_Texture_FogMask;
782 int tex_Texture_Lightmap;
783 int tex_Texture_Deluxemap;
784 int tex_Texture_Attenuation;
785 int tex_Texture_Cube;
786 int tex_Texture_Refraction;
787 int tex_Texture_Reflection;
788 int tex_Texture_ShadowMap2D;
789 int tex_Texture_CubeProjection;
790 int tex_Texture_ScreenNormalMap;
791 int tex_Texture_ScreenDiffuse;
792 int tex_Texture_ScreenSpecular;
793 int tex_Texture_ReflectMask;
794 int tex_Texture_ReflectCube;
795 int tex_Texture_BounceGrid;
796 /// locations of detected uniforms in program object, or -1 if not found
797 int loc_Texture_First;
798 int loc_Texture_Second;
799 int loc_Texture_GammaRamps;
800 int loc_Texture_Normal;
801 int loc_Texture_Color;
802 int loc_Texture_Gloss;
803 int loc_Texture_Glow;
804 int loc_Texture_SecondaryNormal;
805 int loc_Texture_SecondaryColor;
806 int loc_Texture_SecondaryGloss;
807 int loc_Texture_SecondaryGlow;
808 int loc_Texture_Pants;
809 int loc_Texture_Shirt;
810 int loc_Texture_FogHeightTexture;
811 int loc_Texture_FogMask;
812 int loc_Texture_Lightmap;
813 int loc_Texture_Deluxemap;
814 int loc_Texture_Attenuation;
815 int loc_Texture_Cube;
816 int loc_Texture_Refraction;
817 int loc_Texture_Reflection;
818 int loc_Texture_ShadowMap2D;
819 int loc_Texture_CubeProjection;
820 int loc_Texture_ScreenNormalMap;
821 int loc_Texture_ScreenDiffuse;
822 int loc_Texture_ScreenSpecular;
823 int loc_Texture_ReflectMask;
824 int loc_Texture_ReflectCube;
825 int loc_Texture_BounceGrid;
827 int loc_BloomBlur_Parameters;
829 int loc_Color_Ambient;
830 int loc_Color_Diffuse;
831 int loc_Color_Specular;
835 int loc_DeferredColor_Ambient;
836 int loc_DeferredColor_Diffuse;
837 int loc_DeferredColor_Specular;
838 int loc_DeferredMod_Diffuse;
839 int loc_DeferredMod_Specular;
840 int loc_DistortScaleRefractReflect;
843 int loc_FogHeightFade;
845 int loc_FogPlaneViewDist;
846 int loc_FogRangeRecip;
849 int loc_LightPosition;
850 int loc_OffsetMapping_ScaleSteps;
851 int loc_OffsetMapping_LodDistance;
852 int loc_OffsetMapping_Bias;
854 int loc_ReflectColor;
855 int loc_ReflectFactor;
856 int loc_ReflectOffset;
857 int loc_RefractColor;
859 int loc_ScreenCenterRefractReflect;
860 int loc_ScreenScaleRefractReflect;
861 int loc_ScreenToDepth;
862 int loc_ShadowMap_Parameters;
863 int loc_ShadowMap_TextureScale;
864 int loc_SpecularPower;
865 int loc_Skeletal_Transform12;
870 int loc_ViewTintColor;
872 int loc_ModelToLight;
874 int loc_BackgroundTexMatrix;
875 int loc_ModelViewProjectionMatrix;
876 int loc_ModelViewMatrix;
877 int loc_PixelToScreenTexCoord;
878 int loc_ModelToReflectCube;
879 int loc_ShadowMapMatrix;
880 int loc_BloomColorSubtract;
881 int loc_NormalmapScrollBlend;
882 int loc_BounceGridMatrix;
883 int loc_BounceGridIntensity;
884 /// uniform block bindings
885 int ubibind_Skeletal_Transform12_UniformBlock;
886 /// uniform block indices
887 int ubiloc_Skeletal_Transform12_UniformBlock;
889 r_glsl_permutation_t;
891 #define SHADERPERMUTATION_HASHSIZE 256
894 // non-degradable "lightweight" shader parameters to keep the permutations simpler
895 // these can NOT degrade! only use for simple stuff
898 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
899 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
900 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
901 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
902 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
903 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
904 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
905 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
906 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
907 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
908 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
909 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
910 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
911 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
913 #define SHADERSTATICPARMS_COUNT 14
915 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
916 static int shaderstaticparms_count = 0;
918 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
919 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
921 extern qboolean r_shadow_shadowmapsampler;
922 extern int r_shadow_shadowmappcf;
923 qboolean R_CompileShader_CheckStaticParms(void)
925 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
926 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
927 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
930 if (r_glsl_saturation_redcompensate.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
932 if (r_glsl_vertextextureblend_usebothalphas.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
934 if (r_shadow_glossexact.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
936 if (r_glsl_postprocess.integer)
938 if (r_glsl_postprocess_uservec1_enable.integer)
939 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
940 if (r_glsl_postprocess_uservec2_enable.integer)
941 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
942 if (r_glsl_postprocess_uservec3_enable.integer)
943 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
944 if (r_glsl_postprocess_uservec4_enable.integer)
945 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
948 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
949 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
950 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
952 if (r_shadow_shadowmapsampler)
953 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
954 if (r_shadow_shadowmappcf > 1)
955 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
956 else if (r_shadow_shadowmappcf)
957 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
958 if (r_celshading.integer)
959 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
960 if (r_celoutlines.integer)
961 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
963 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
966 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
967 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
968 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
970 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
971 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
973 shaderstaticparms_count = 0;
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
980 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
981 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
982 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
983 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
984 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
985 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
986 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
987 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
988 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
989 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
992 /// information about each possible shader permutation
993 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
994 /// currently selected permutation
995 r_glsl_permutation_t *r_glsl_permutation;
996 /// storage for permutations linked in the hash table
997 memexpandablearray_t r_glsl_permutationarray;
999 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1001 //unsigned int hashdepth = 0;
1002 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1003 r_glsl_permutation_t *p;
1004 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1006 if (p->mode == mode && p->permutation == permutation)
1008 //if (hashdepth > 10)
1009 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1014 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1016 p->permutation = permutation;
1017 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1018 r_glsl_permutationhash[mode][hashindex] = p;
1019 //if (hashdepth > 10)
1020 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1024 static char *R_ShaderStrCat(const char **strings)
1027 const char **p = strings;
1030 for (p = strings;(t = *p);p++)
1033 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1035 for (p = strings;(t = *p);p++)
1045 static char *R_ShaderStrCat(const char **strings);
1046 static void R_InitShaderModeInfo(void)
1049 shadermodeinfo_t *modeinfo;
1050 // 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)
1051 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1053 for (i = 0; i < SHADERMODE_COUNT; i++)
1055 char filename[MAX_QPATH];
1056 modeinfo = &shadermodeinfo[language][i];
1057 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1058 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1059 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1060 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1065 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1068 // if the mode has no filename we have to return the builtin string
1069 if (builtinonly || !modeinfo->filename)
1070 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1071 // note that FS_LoadFile appends a 0 byte to make it a valid string
1072 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1075 if (printfromdisknotice)
1076 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1077 return shaderstring;
1079 // fall back to builtinstring
1080 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1083 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1088 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1090 char permutationname[256];
1091 int vertstrings_count = 0;
1092 int geomstrings_count = 0;
1093 int fragstrings_count = 0;
1094 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1103 permutationname[0] = 0;
1104 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1106 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1108 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1109 if(vid.support.glshaderversion >= 140)
1111 vertstrings_list[vertstrings_count++] = "#version 140\n";
1112 geomstrings_list[geomstrings_count++] = "#version 140\n";
1113 fragstrings_list[fragstrings_count++] = "#version 140\n";
1114 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1115 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1116 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1118 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1119 else if(vid.support.glshaderversion >= 130)
1121 vertstrings_list[vertstrings_count++] = "#version 130\n";
1122 geomstrings_list[geomstrings_count++] = "#version 130\n";
1123 fragstrings_list[fragstrings_count++] = "#version 130\n";
1124 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1125 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1126 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1128 // if we can do #version 120, we should (this adds the invariant keyword)
1129 else if(vid.support.glshaderversion >= 120)
1131 vertstrings_list[vertstrings_count++] = "#version 120\n";
1132 geomstrings_list[geomstrings_count++] = "#version 120\n";
1133 fragstrings_list[fragstrings_count++] = "#version 120\n";
1134 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1135 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1136 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1138 // GLES also adds several things from GLSL120
1139 switch(vid.renderpath)
1141 case RENDERPATH_GLES2:
1142 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1143 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1144 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1150 // the first pretext is which type of shader to compile as
1151 // (later these will all be bound together as a program object)
1152 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1153 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1154 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1156 // the second pretext is the mode (for example a light source)
1157 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1158 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1159 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1160 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1162 // now add all the permutation pretexts
1163 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1165 if (permutation & (1ll<<i))
1167 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1168 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1169 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1170 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1174 // keep line numbers correct
1175 vertstrings_list[vertstrings_count++] = "\n";
1176 geomstrings_list[geomstrings_count++] = "\n";
1177 fragstrings_list[fragstrings_count++] = "\n";
1182 R_CompileShader_AddStaticParms(mode, permutation);
1183 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1184 vertstrings_count += shaderstaticparms_count;
1185 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1186 geomstrings_count += shaderstaticparms_count;
1187 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1188 fragstrings_count += shaderstaticparms_count;
1190 // now append the shader text itself
1191 vertstrings_list[vertstrings_count++] = sourcestring;
1192 geomstrings_list[geomstrings_count++] = sourcestring;
1193 fragstrings_list[fragstrings_count++] = sourcestring;
1195 // compile the shader program
1196 if (vertstrings_count + geomstrings_count + fragstrings_count)
1197 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1201 qglUseProgram(p->program);CHECKGLERROR
1202 // look up all the uniform variable names we care about, so we don't
1203 // have to look them up every time we set them
1208 GLint activeuniformindex = 0;
1209 GLint numactiveuniforms = 0;
1210 char uniformname[128];
1211 GLsizei uniformnamelength = 0;
1212 GLint uniformsize = 0;
1213 GLenum uniformtype = 0;
1214 memset(uniformname, 0, sizeof(uniformname));
1215 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1216 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1217 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1219 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1220 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1225 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1226 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1227 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1228 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1229 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1230 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1231 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1232 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1233 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1234 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1235 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1236 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1237 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1238 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1239 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1240 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1241 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1242 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1243 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1244 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1245 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1246 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1247 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1248 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1249 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1250 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1251 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1252 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1253 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1254 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1255 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1256 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1257 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1258 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1259 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1260 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1261 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1262 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1263 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1264 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1265 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1266 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1267 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1268 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1269 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1270 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1271 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1272 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1273 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1274 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1275 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1276 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1277 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1278 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1279 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1280 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1281 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1282 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1283 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1284 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1285 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1286 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1287 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1288 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1289 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1290 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1291 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1292 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1293 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1294 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1295 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1296 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1297 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1298 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1299 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1300 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1301 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1302 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1303 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1304 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1305 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1306 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1307 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1308 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1309 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1310 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1311 // initialize the samplers to refer to the texture units we use
1312 p->tex_Texture_First = -1;
1313 p->tex_Texture_Second = -1;
1314 p->tex_Texture_GammaRamps = -1;
1315 p->tex_Texture_Normal = -1;
1316 p->tex_Texture_Color = -1;
1317 p->tex_Texture_Gloss = -1;
1318 p->tex_Texture_Glow = -1;
1319 p->tex_Texture_SecondaryNormal = -1;
1320 p->tex_Texture_SecondaryColor = -1;
1321 p->tex_Texture_SecondaryGloss = -1;
1322 p->tex_Texture_SecondaryGlow = -1;
1323 p->tex_Texture_Pants = -1;
1324 p->tex_Texture_Shirt = -1;
1325 p->tex_Texture_FogHeightTexture = -1;
1326 p->tex_Texture_FogMask = -1;
1327 p->tex_Texture_Lightmap = -1;
1328 p->tex_Texture_Deluxemap = -1;
1329 p->tex_Texture_Attenuation = -1;
1330 p->tex_Texture_Cube = -1;
1331 p->tex_Texture_Refraction = -1;
1332 p->tex_Texture_Reflection = -1;
1333 p->tex_Texture_ShadowMap2D = -1;
1334 p->tex_Texture_CubeProjection = -1;
1335 p->tex_Texture_ScreenNormalMap = -1;
1336 p->tex_Texture_ScreenDiffuse = -1;
1337 p->tex_Texture_ScreenSpecular = -1;
1338 p->tex_Texture_ReflectMask = -1;
1339 p->tex_Texture_ReflectCube = -1;
1340 p->tex_Texture_BounceGrid = -1;
1341 // bind the texture samplers in use
1343 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1344 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1345 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1346 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1347 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1348 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1349 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1350 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1351 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1352 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1353 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1354 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1355 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1356 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1357 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1358 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1359 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1360 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1361 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1362 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1363 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1364 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1365 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1366 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1367 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1368 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1369 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1370 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1371 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1372 // get the uniform block indices so we can bind them
1373 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1374 if (vid.support.arb_uniform_buffer_object)
1375 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1378 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1379 // clear the uniform block bindings
1380 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1381 // bind the uniform blocks in use
1383 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1384 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1386 // we're done compiling and setting up the shader, at least until it is used
1388 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1391 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1395 Mem_Free(sourcestring);
1398 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1400 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1401 if (r_glsl_permutation != perm)
1403 r_glsl_permutation = perm;
1404 if (!r_glsl_permutation->program)
1406 if (!r_glsl_permutation->compiled)
1408 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1409 R_GLSL_CompilePermutation(perm, mode, permutation);
1411 if (!r_glsl_permutation->program)
1413 // remove features until we find a valid permutation
1415 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1417 // reduce i more quickly whenever it would not remove any bits
1418 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1419 if (!(permutation & j))
1422 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1423 if (!r_glsl_permutation->compiled)
1424 R_GLSL_CompilePermutation(perm, mode, permutation);
1425 if (r_glsl_permutation->program)
1428 if (i >= SHADERPERMUTATION_COUNT)
1430 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1431 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1432 qglUseProgram(0);CHECKGLERROR
1433 return; // no bit left to clear, entire mode is broken
1438 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1440 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1441 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1442 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1450 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1451 extern D3DCAPS9 vid_d3d9caps;
1454 struct r_hlsl_permutation_s;
1455 typedef struct r_hlsl_permutation_s
1457 /// hash lookup data
1458 struct r_hlsl_permutation_s *hashnext;
1460 dpuint64 permutation;
1462 /// indicates if we have tried compiling this permutation already
1464 /// NULL if compilation failed
1465 IDirect3DVertexShader9 *vertexshader;
1466 IDirect3DPixelShader9 *pixelshader;
1468 r_hlsl_permutation_t;
1470 typedef enum D3DVSREGISTER_e
1472 D3DVSREGISTER_TexMatrix = 0, // float4x4
1473 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1474 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1475 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1476 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1477 D3DVSREGISTER_ModelToLight = 20, // float4x4
1478 D3DVSREGISTER_EyePosition = 24,
1479 D3DVSREGISTER_FogPlane = 25,
1480 D3DVSREGISTER_LightDir = 26,
1481 D3DVSREGISTER_LightPosition = 27,
1485 typedef enum D3DPSREGISTER_e
1487 D3DPSREGISTER_Alpha = 0,
1488 D3DPSREGISTER_BloomBlur_Parameters = 1,
1489 D3DPSREGISTER_ClientTime = 2,
1490 D3DPSREGISTER_Color_Ambient = 3,
1491 D3DPSREGISTER_Color_Diffuse = 4,
1492 D3DPSREGISTER_Color_Specular = 5,
1493 D3DPSREGISTER_Color_Glow = 6,
1494 D3DPSREGISTER_Color_Pants = 7,
1495 D3DPSREGISTER_Color_Shirt = 8,
1496 D3DPSREGISTER_DeferredColor_Ambient = 9,
1497 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1498 D3DPSREGISTER_DeferredColor_Specular = 11,
1499 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1500 D3DPSREGISTER_DeferredMod_Specular = 13,
1501 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1502 D3DPSREGISTER_EyePosition = 15, // unused
1503 D3DPSREGISTER_FogColor = 16,
1504 D3DPSREGISTER_FogHeightFade = 17,
1505 D3DPSREGISTER_FogPlane = 18,
1506 D3DPSREGISTER_FogPlaneViewDist = 19,
1507 D3DPSREGISTER_FogRangeRecip = 20,
1508 D3DPSREGISTER_LightColor = 21,
1509 D3DPSREGISTER_LightDir = 22, // unused
1510 D3DPSREGISTER_LightPosition = 23,
1511 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1512 D3DPSREGISTER_PixelSize = 25,
1513 D3DPSREGISTER_ReflectColor = 26,
1514 D3DPSREGISTER_ReflectFactor = 27,
1515 D3DPSREGISTER_ReflectOffset = 28,
1516 D3DPSREGISTER_RefractColor = 29,
1517 D3DPSREGISTER_Saturation = 30,
1518 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1519 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1520 D3DPSREGISTER_ScreenToDepth = 33,
1521 D3DPSREGISTER_ShadowMap_Parameters = 34,
1522 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1523 D3DPSREGISTER_SpecularPower = 36,
1524 D3DPSREGISTER_UserVec1 = 37,
1525 D3DPSREGISTER_UserVec2 = 38,
1526 D3DPSREGISTER_UserVec3 = 39,
1527 D3DPSREGISTER_UserVec4 = 40,
1528 D3DPSREGISTER_ViewTintColor = 41,
1529 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1530 D3DPSREGISTER_BloomColorSubtract = 43,
1531 D3DPSREGISTER_ViewToLight = 44, // float4x4
1532 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1533 D3DPSREGISTER_NormalmapScrollBlend = 52,
1534 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1535 D3DPSREGISTER_OffsetMapping_Bias = 54,
1540 /// information about each possible shader permutation
1541 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1542 /// currently selected permutation
1543 r_hlsl_permutation_t *r_hlsl_permutation;
1544 /// storage for permutations linked in the hash table
1545 memexpandablearray_t r_hlsl_permutationarray;
1547 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1549 //unsigned int hashdepth = 0;
1550 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1551 r_hlsl_permutation_t *p;
1552 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1554 if (p->mode == mode && p->permutation == permutation)
1556 //if (hashdepth > 10)
1557 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1562 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1564 p->permutation = permutation;
1565 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1566 r_hlsl_permutationhash[mode][hashindex] = p;
1567 //if (hashdepth > 10)
1568 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1573 //#include <d3dx9shader.h>
1574 //#include <d3dx9mesh.h>
1576 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1578 DWORD *vsbin = NULL;
1579 DWORD *psbin = NULL;
1580 fs_offset_t vsbinsize;
1581 fs_offset_t psbinsize;
1582 // IDirect3DVertexShader9 *vs = NULL;
1583 // IDirect3DPixelShader9 *ps = NULL;
1584 ID3DXBuffer *vslog = NULL;
1585 ID3DXBuffer *vsbuffer = NULL;
1586 ID3DXConstantTable *vsconstanttable = NULL;
1587 ID3DXBuffer *pslog = NULL;
1588 ID3DXBuffer *psbuffer = NULL;
1589 ID3DXConstantTable *psconstanttable = NULL;
1592 char temp[MAX_INPUTLINE];
1593 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1595 qboolean debugshader = gl_paranoid.integer != 0;
1596 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1597 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1600 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1601 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1603 if ((!vsbin && vertstring) || (!psbin && fragstring))
1605 const char* dllnames_d3dx9 [] =
1629 dllhandle_t d3dx9_dll = NULL;
1630 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1631 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1632 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1633 dllfunction_t d3dx9_dllfuncs[] =
1635 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1636 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1637 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1640 // 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...
1641 #ifndef ID3DXBuffer_GetBufferPointer
1642 #if !defined(__cplusplus) || defined(CINTERFACE)
1643 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1644 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1645 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1647 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1648 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1649 #define ID3DXBuffer_Release(p) (p)->Release()
1652 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1654 DWORD shaderflags = 0;
1656 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1657 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1658 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1659 if (vertstring && vertstring[0])
1663 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1664 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1667 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1670 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1671 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1672 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1673 ID3DXBuffer_Release(vsbuffer);
1677 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1678 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1679 ID3DXBuffer_Release(vslog);
1682 if (fragstring && fragstring[0])
1686 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1687 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1690 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1693 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1694 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1695 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1696 ID3DXBuffer_Release(psbuffer);
1700 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1701 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1702 ID3DXBuffer_Release(pslog);
1705 Sys_UnloadLibrary(&d3dx9_dll);
1708 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1712 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1713 if (FAILED(vsresult))
1714 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1715 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1716 if (FAILED(psresult))
1717 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1719 // free the shader data
1720 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1721 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1724 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1727 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1728 int vertstring_length = 0;
1729 int geomstring_length = 0;
1730 int fragstring_length = 0;
1733 char *vertstring, *geomstring, *fragstring;
1734 char permutationname[256];
1735 char cachename[256];
1736 int vertstrings_count = 0;
1737 int geomstrings_count = 0;
1738 int fragstrings_count = 0;
1739 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1740 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1741 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1746 p->vertexshader = NULL;
1747 p->pixelshader = NULL;
1749 permutationname[0] = 0;
1751 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1753 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1754 strlcat(cachename, "hlsl/", sizeof(cachename));
1756 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1757 vertstrings_count = 0;
1758 geomstrings_count = 0;
1759 fragstrings_count = 0;
1760 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1761 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1762 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1764 // the first pretext is which type of shader to compile as
1765 // (later these will all be bound together as a program object)
1766 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1767 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1768 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1770 // the second pretext is the mode (for example a light source)
1771 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1772 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1773 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1774 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1775 strlcat(cachename, modeinfo->name, sizeof(cachename));
1777 // now add all the permutation pretexts
1778 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1780 if (permutation & (1ll<<i))
1782 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1783 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1784 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1785 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1786 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1790 // keep line numbers correct
1791 vertstrings_list[vertstrings_count++] = "\n";
1792 geomstrings_list[geomstrings_count++] = "\n";
1793 fragstrings_list[fragstrings_count++] = "\n";
1798 R_CompileShader_AddStaticParms(mode, permutation);
1799 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1800 vertstrings_count += shaderstaticparms_count;
1801 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1802 geomstrings_count += shaderstaticparms_count;
1803 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1804 fragstrings_count += shaderstaticparms_count;
1806 // replace spaces in the cachename with _ characters
1807 for (i = 0;cachename[i];i++)
1808 if (cachename[i] == ' ')
1811 // now append the shader text itself
1812 vertstrings_list[vertstrings_count++] = sourcestring;
1813 geomstrings_list[geomstrings_count++] = sourcestring;
1814 fragstrings_list[fragstrings_count++] = sourcestring;
1816 vertstring_length = 0;
1817 for (i = 0;i < vertstrings_count;i++)
1818 vertstring_length += (int)strlen(vertstrings_list[i]);
1819 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1820 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1821 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1823 geomstring_length = 0;
1824 for (i = 0;i < geomstrings_count;i++)
1825 geomstring_length += (int)strlen(geomstrings_list[i]);
1826 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1827 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1828 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1830 fragstring_length = 0;
1831 for (i = 0;i < fragstrings_count;i++)
1832 fragstring_length += (int)strlen(fragstrings_list[i]);
1833 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1834 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1835 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1837 // try to load the cached shader, or generate one
1838 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1840 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1841 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1843 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1847 Mem_Free(vertstring);
1849 Mem_Free(geomstring);
1851 Mem_Free(fragstring);
1853 Mem_Free(sourcestring);
1856 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1857 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1858 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);}
1859 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);}
1860 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);}
1861 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);}
1863 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1864 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1865 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);}
1866 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);}
1867 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);}
1868 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);}
1870 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1872 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1873 if (r_hlsl_permutation != perm)
1875 r_hlsl_permutation = perm;
1876 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1878 if (!r_hlsl_permutation->compiled)
1879 R_HLSL_CompilePermutation(perm, mode, permutation);
1880 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1882 // remove features until we find a valid permutation
1884 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886 // reduce i more quickly whenever it would not remove any bits
1887 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1888 if (!(permutation & j))
1891 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1892 if (!r_hlsl_permutation->compiled)
1893 R_HLSL_CompilePermutation(perm, mode, permutation);
1894 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1897 if (i >= SHADERPERMUTATION_COUNT)
1899 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1900 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1901 return; // no bit left to clear, entire mode is broken
1905 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1906 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1908 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1909 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1910 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1914 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1916 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1917 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1918 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1919 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1922 void R_GLSL_Restart_f(void)
1924 unsigned int i, limit;
1925 switch(vid.renderpath)
1927 case RENDERPATH_D3D9:
1930 r_hlsl_permutation_t *p;
1931 r_hlsl_permutation = NULL;
1932 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1933 for (i = 0;i < limit;i++)
1935 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1937 if (p->vertexshader)
1938 IDirect3DVertexShader9_Release(p->vertexshader);
1940 IDirect3DPixelShader9_Release(p->pixelshader);
1941 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1944 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1948 case RENDERPATH_D3D10:
1949 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951 case RENDERPATH_D3D11:
1952 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954 case RENDERPATH_GL20:
1955 case RENDERPATH_GLES2:
1957 r_glsl_permutation_t *p;
1958 r_glsl_permutation = NULL;
1959 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1960 for (i = 0;i < limit;i++)
1962 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1964 GL_Backend_FreeProgram(p->program);
1965 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1968 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1971 case RENDERPATH_GL11:
1972 case RENDERPATH_GL13:
1973 case RENDERPATH_GLES1:
1975 case RENDERPATH_SOFT:
1980 static void R_GLSL_DumpShader_f(void)
1982 int i, language, mode, dupe;
1984 shadermodeinfo_t *modeinfo;
1987 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1989 modeinfo = shadermodeinfo[language];
1990 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1992 // don't dump the same file multiple times (most or all shaders come from the same file)
1993 for (dupe = mode - 1;dupe >= 0;dupe--)
1994 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1998 text = modeinfo[mode].builtinstring;
2001 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
2004 FS_Print(file, "/* The engine may define the following macros:\n");
2005 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
2006 for (i = 0;i < SHADERMODE_COUNT;i++)
2007 FS_Print(file, modeinfo[i].pretext);
2008 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2009 FS_Print(file, shaderpermutationinfo[i].pretext);
2010 FS_Print(file, "*/\n");
2011 FS_Print(file, text);
2013 Con_Printf("%s written\n", modeinfo[mode].filename);
2016 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2021 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2023 dpuint64 permutation = 0;
2024 if (r_trippy.integer && !notrippy)
2025 permutation |= SHADERPERMUTATION_TRIPPY;
2026 permutation |= SHADERPERMUTATION_VIEWTINT;
2028 permutation |= SHADERPERMUTATION_DIFFUSE;
2030 permutation |= SHADERPERMUTATION_SPECULAR;
2031 if (texturemode == GL_MODULATE)
2032 permutation |= SHADERPERMUTATION_COLORMAPPING;
2033 else if (texturemode == GL_ADD)
2034 permutation |= SHADERPERMUTATION_GLOW;
2035 else if (texturemode == GL_DECAL)
2036 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2037 if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2038 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2039 if (suppresstexalpha)
2040 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2042 texturemode = GL_MODULATE;
2043 if (vid.allowalphatocoverage)
2044 GL_AlphaToCoverage(false);
2045 switch (vid.renderpath)
2047 case RENDERPATH_D3D9:
2049 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2050 R_Mesh_TexBind(GL20TU_FIRST , first );
2051 R_Mesh_TexBind(GL20TU_SECOND, second);
2052 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2053 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2056 case RENDERPATH_D3D10:
2057 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2059 case RENDERPATH_D3D11:
2060 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2062 case RENDERPATH_GL20:
2063 case RENDERPATH_GLES2:
2064 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2065 if (r_glsl_permutation->tex_Texture_First >= 0)
2066 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2067 if (r_glsl_permutation->tex_Texture_Second >= 0)
2068 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2069 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2070 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2072 case RENDERPATH_GL13:
2073 case RENDERPATH_GLES1:
2074 R_Mesh_TexBind(0, first );
2075 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2076 R_Mesh_TexMatrix(0, NULL);
2077 R_Mesh_TexBind(1, second);
2080 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2081 R_Mesh_TexMatrix(1, NULL);
2084 case RENDERPATH_GL11:
2085 R_Mesh_TexBind(0, first );
2086 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2087 R_Mesh_TexMatrix(0, NULL);
2089 case RENDERPATH_SOFT:
2090 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2091 R_Mesh_TexBind(GL20TU_FIRST , first );
2092 R_Mesh_TexBind(GL20TU_SECOND, second);
2097 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2099 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2102 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2104 dpuint64 permutation = 0;
2105 if (r_trippy.integer && !notrippy)
2106 permutation |= SHADERPERMUTATION_TRIPPY;
2108 permutation |= SHADERPERMUTATION_DEPTHRGB;
2110 permutation |= SHADERPERMUTATION_SKELETAL;
2112 if (vid.allowalphatocoverage)
2113 GL_AlphaToCoverage(false);
2114 switch (vid.renderpath)
2116 case RENDERPATH_D3D9:
2118 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2121 case RENDERPATH_D3D10:
2122 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2124 case RENDERPATH_D3D11:
2125 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2127 case RENDERPATH_GL20:
2128 case RENDERPATH_GLES2:
2129 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2130 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2131 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);
2134 case RENDERPATH_GL13:
2135 case RENDERPATH_GLES1:
2136 R_Mesh_TexBind(0, 0);
2137 R_Mesh_TexBind(1, 0);
2139 case RENDERPATH_GL11:
2140 R_Mesh_TexBind(0, 0);
2142 case RENDERPATH_SOFT:
2143 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2148 extern qboolean r_shadow_usingdeferredprepass;
2149 extern rtexture_t *r_shadow_attenuationgradienttexture;
2150 extern rtexture_t *r_shadow_attenuation2dtexture;
2151 extern rtexture_t *r_shadow_attenuation3dtexture;
2152 extern qboolean r_shadow_usingshadowmap2d;
2153 extern qboolean r_shadow_usingshadowmaportho;
2154 extern float r_shadow_modelshadowmap_texturescale[4];
2155 extern float r_shadow_modelshadowmap_parameters[4];
2156 extern float r_shadow_lightshadowmap_texturescale[4];
2157 extern float r_shadow_lightshadowmap_parameters[4];
2158 extern qboolean r_shadow_shadowmapvsdct;
2159 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2160 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2161 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2162 extern matrix4x4_t r_shadow_shadowmapmatrix;
2163 extern int r_shadow_prepass_width;
2164 extern int r_shadow_prepass_height;
2165 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2166 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2167 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2168 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2170 #define BLENDFUNC_ALLOWS_COLORMOD 1
2171 #define BLENDFUNC_ALLOWS_FOG 2
2172 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2173 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2174 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2175 static int R_BlendFuncFlags(int src, int dst)
2179 // a blendfunc allows colormod if:
2180 // a) it can never keep the destination pixel invariant, or
2181 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2182 // this is to prevent unintended side effects from colormod
2184 // a blendfunc allows fog if:
2185 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2186 // this is to prevent unintended side effects from fog
2188 // these checks are the output of fogeval.pl
2190 r |= BLENDFUNC_ALLOWS_COLORMOD;
2191 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2192 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2193 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2194 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2195 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2197 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2198 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2199 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2200 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2201 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2202 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2203 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2204 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2205 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2206 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2207 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2208 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2209 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2210 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2211 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2216 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)
2218 // select a permutation of the lighting shader appropriate to this
2219 // combination of texture, entity, light source, and fogging, only use the
2220 // minimum features necessary to avoid wasting rendering time in the
2221 // fragment shader on features that are not being used
2222 dpuint64 permutation = 0;
2223 unsigned int mode = 0;
2225 texture_t *t = rsurface.texture;
2227 matrix4x4_t tempmatrix;
2228 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2229 if (r_trippy.integer && !notrippy)
2230 permutation |= SHADERPERMUTATION_TRIPPY;
2231 if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2232 permutation |= SHADERPERMUTATION_ALPHAKILL;
2233 if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2234 permutation |= SHADERPERMUTATION_OCCLUDE;
2235 if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2236 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2237 if (rsurfacepass == RSURFPASS_BACKGROUND)
2239 // distorted background
2240 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2242 mode = SHADERMODE_WATER;
2243 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2244 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2245 if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2247 // this is the right thing to do for wateralpha
2248 GL_BlendFunc(GL_ONE, GL_ZERO);
2249 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2253 // this is the right thing to do for entity alpha
2254 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2255 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2258 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2260 mode = SHADERMODE_REFRACTION;
2261 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2264 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2268 mode = SHADERMODE_GENERIC;
2269 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2270 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2271 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2273 if (vid.allowalphatocoverage)
2274 GL_AlphaToCoverage(false);
2276 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2278 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2280 switch(t->offsetmapping)
2282 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2283 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285 case OFFSETMAPPING_OFF: break;
2288 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290 // normalmap (deferred prepass), may use alpha test on diffuse
2291 mode = SHADERMODE_DEFERREDGEOMETRY;
2292 GL_BlendFunc(GL_ONE, GL_ZERO);
2293 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2294 if (vid.allowalphatocoverage)
2295 GL_AlphaToCoverage(false);
2297 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2299 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2301 switch(t->offsetmapping)
2303 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2304 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2305 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306 case OFFSETMAPPING_OFF: break;
2309 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2310 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2311 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2312 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2314 mode = SHADERMODE_LIGHTSOURCE;
2315 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2316 permutation |= SHADERPERMUTATION_CUBEFILTER;
2317 if (VectorLength2(rtlightdiffuse) > 0)
2318 permutation |= SHADERPERMUTATION_DIFFUSE;
2319 if (VectorLength2(rtlightspecular) > 0)
2320 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2321 if (r_refdef.fogenabled)
2322 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323 if (t->colormapping)
2324 permutation |= SHADERPERMUTATION_COLORMAPPING;
2325 if (r_shadow_usingshadowmap2d)
2327 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2328 if(r_shadow_shadowmapvsdct)
2329 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2331 if (r_shadow_shadowmap2ddepthbuffer)
2332 permutation |= SHADERPERMUTATION_DEPTHRGB;
2334 if (t->reflectmasktexture)
2335 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2336 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2337 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2338 if (vid.allowalphatocoverage)
2339 GL_AlphaToCoverage(false);
2341 else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2343 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2345 switch(t->offsetmapping)
2347 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350 case OFFSETMAPPING_OFF: break;
2353 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2356 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2357 // directional model lighting
2358 mode = SHADERMODE_LIGHTDIRECTION;
2359 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360 permutation |= SHADERPERMUTATION_GLOW;
2361 if (VectorLength2(t->render_modellight_diffuse))
2362 permutation |= SHADERPERMUTATION_DIFFUSE;
2363 if (VectorLength2(t->render_modellight_specular) > 0)
2364 permutation |= SHADERPERMUTATION_SPECULAR;
2365 if (r_refdef.fogenabled)
2366 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2367 if (t->colormapping)
2368 permutation |= SHADERPERMUTATION_COLORMAPPING;
2369 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2372 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374 if (r_shadow_shadowmap2ddepthbuffer)
2375 permutation |= SHADERPERMUTATION_DEPTHRGB;
2377 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378 permutation |= SHADERPERMUTATION_REFLECTION;
2379 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2380 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381 if (t->reflectmasktexture)
2382 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2385 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2386 if (r_shadow_bouncegrid_state.directional)
2387 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2389 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2390 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2391 // when using alphatocoverage, we don't need alphakill
2392 if (vid.allowalphatocoverage)
2394 if (r_transparent_alphatocoverage.integer)
2396 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2397 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2400 GL_AlphaToCoverage(false);
2405 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2407 switch(t->offsetmapping)
2409 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2410 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412 case OFFSETMAPPING_OFF: break;
2415 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2416 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2417 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2418 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2420 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2421 permutation |= SHADERPERMUTATION_GLOW;
2422 if (r_refdef.fogenabled)
2423 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2424 if (t->colormapping)
2425 permutation |= SHADERPERMUTATION_COLORMAPPING;
2426 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2428 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2429 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2431 if (r_shadow_shadowmap2ddepthbuffer)
2432 permutation |= SHADERPERMUTATION_DEPTHRGB;
2434 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435 permutation |= SHADERPERMUTATION_REFLECTION;
2436 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2437 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438 if (t->reflectmasktexture)
2439 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440 if (FAKELIGHT_ENABLED)
2442 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443 mode = SHADERMODE_FAKELIGHT;
2444 permutation |= SHADERPERMUTATION_DIFFUSE;
2445 if (VectorLength2(t->render_lightmap_specular) > 0)
2446 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2448 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2450 // deluxemapping (light direction texture)
2451 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2454 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455 permutation |= SHADERPERMUTATION_DIFFUSE;
2456 if (VectorLength2(t->render_lightmap_specular) > 0)
2457 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2459 else if (r_glsl_deluxemapping.integer >= 2)
2461 // fake deluxemapping (uniform light direction in tangentspace)
2462 if (rsurface.uselightmaptexture)
2463 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2465 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2466 permutation |= SHADERPERMUTATION_DIFFUSE;
2467 if (VectorLength2(t->render_lightmap_specular) > 0)
2468 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2470 else if (rsurface.uselightmaptexture)
2472 // ordinary lightmapping (q1bsp, q3bsp)
2473 mode = SHADERMODE_LIGHTMAP;
2477 // ordinary vertex coloring (q3bsp)
2478 mode = SHADERMODE_VERTEXCOLOR;
2480 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2482 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2483 if (r_shadow_bouncegrid_state.directional)
2484 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2486 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2487 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2488 // when using alphatocoverage, we don't need alphakill
2489 if (vid.allowalphatocoverage)
2491 if (r_transparent_alphatocoverage.integer)
2493 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2494 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2497 GL_AlphaToCoverage(false);
2500 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2501 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2502 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2503 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2504 switch(vid.renderpath)
2506 case RENDERPATH_D3D9:
2508 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);
2509 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2510 R_SetupShader_SetPermutationHLSL(mode, permutation);
2511 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2512 if (mode == SHADERMODE_LIGHTSOURCE)
2514 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2515 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2519 if (mode == SHADERMODE_LIGHTDIRECTION)
2521 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2524 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2525 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2526 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2527 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2530 if (mode == SHADERMODE_LIGHTSOURCE)
2532 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2534 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2535 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2536 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2538 // additive passes are only darkened by fog, not tinted
2539 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2544 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2545 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2546 if (mode == SHADERMODE_FLATCOLOR)
2548 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2550 else if (mode == SHADERMODE_LIGHTDIRECTION)
2552 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2553 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2554 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2555 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2556 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2560 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2561 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2562 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2564 // additive passes are only darkened by fog, not tinted
2565 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2566 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2569 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);
2570 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2571 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2572 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2573 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2574 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2575 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2576 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2577 if (mode == SHADERMODE_WATER)
2578 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2580 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2582 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2583 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2587 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2588 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2590 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2591 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2592 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2593 if (t->pantstexture)
2594 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2596 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2597 if (t->shirttexture)
2598 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2600 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2601 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2602 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2603 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2604 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2605 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2606 r_glsl_offsetmapping_scale.value*t->offsetscale,
2607 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2608 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2609 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2611 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2612 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2613 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2614 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2616 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2617 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2618 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2619 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2620 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2621 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2622 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2623 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2624 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2625 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2626 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2627 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2628 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2629 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2630 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2631 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2632 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2633 if (rsurfacepass == RSURFPASS_BACKGROUND)
2635 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2636 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2637 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2643 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2644 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2645 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2646 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2648 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2649 if (rsurface.rtlight)
2651 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2652 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2657 case RENDERPATH_D3D10:
2658 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2660 case RENDERPATH_D3D11:
2661 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2663 case RENDERPATH_GL20:
2664 case RENDERPATH_GLES2:
2665 if (!vid.useinterleavedarrays)
2667 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);
2668 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2669 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2670 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2671 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2672 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2673 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2674 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2675 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2676 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2677 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2681 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);
2682 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2684 // this has to be after RSurf_PrepareVerticesForBatch
2685 if (rsurface.batchskeletaltransform3x4buffer)
2686 permutation |= SHADERPERMUTATION_SKELETAL;
2687 R_SetupShader_SetPermutationGLSL(mode, permutation);
2688 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2689 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);
2691 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692 if (mode == SHADERMODE_LIGHTSOURCE)
2694 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2697 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2698 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2699 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2701 // additive passes are only darkened by fog, not tinted
2702 if (r_glsl_permutation->loc_FogColor >= 0)
2703 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704 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);
2708 if (mode == SHADERMODE_FLATCOLOR)
2710 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]);
2712 else if (mode == SHADERMODE_LIGHTDIRECTION)
2714 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]);
2715 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]);
2716 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]);
2717 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]);
2718 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]);
2719 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2720 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]);
2724 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]);
2725 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]);
2726 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]);
2727 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]);
2728 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]);
2730 // additive passes are only darkened by fog, not tinted
2731 if (r_glsl_permutation->loc_FogColor >= 0)
2733 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2736 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2738 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);
2739 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]);
2740 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]);
2741 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);
2742 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);
2743 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2744 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2745 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);
2746 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2748 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2753 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]);
2754 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]);
2758 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]);
2759 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]);
2762 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]);
2763 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));
2764 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2765 if (r_glsl_permutation->loc_Color_Pants >= 0)
2767 if (t->pantstexture)
2768 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2770 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2772 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2774 if (t->shirttexture)
2775 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2777 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2779 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]);
2780 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2781 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2782 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2783 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2784 r_glsl_offsetmapping_scale.value*t->offsetscale,
2785 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2786 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2787 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2789 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);
2790 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2791 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]);
2792 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2793 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);}
2794 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2796 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2797 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2798 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2799 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , t->nmaptexture );
2800 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , t->basetexture );
2801 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , t->glosstexture );
2802 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , t->glowtexture );
2803 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , t->backgroundnmaptexture );
2804 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , t->backgroundbasetexture );
2805 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , t->backgroundglosstexture );
2806 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , t->backgroundglowtexture );
2807 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , t->pantstexture );
2808 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , t->shirttexture );
2809 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , t->reflectmasktexture );
2810 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2811 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2812 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2813 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2814 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2815 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2816 if (rsurfacepass == RSURFPASS_BACKGROUND)
2818 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);
2819 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);
2820 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);
2824 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);
2826 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2827 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2828 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2829 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2831 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2832 if (rsurface.rtlight)
2834 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2835 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2838 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2841 case RENDERPATH_GL11:
2842 case RENDERPATH_GL13:
2843 case RENDERPATH_GLES1:
2845 case RENDERPATH_SOFT:
2846 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);
2847 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2848 R_SetupShader_SetPermutationSoft(mode, permutation);
2849 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2850 if (mode == SHADERMODE_LIGHTSOURCE)
2852 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2854 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2855 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2856 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2859 // additive passes are only darkened by fog, not tinted
2860 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2861 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2865 if (mode == SHADERMODE_FLATCOLOR)
2867 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2869 else if (mode == SHADERMODE_LIGHTDIRECTION)
2871 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2872 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2873 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2874 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2875 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2879 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2880 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2881 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2883 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2885 // additive passes are only darkened by fog, not tinted
2886 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2887 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2889 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2890 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);
2891 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]);
2892 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]);
2893 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2894 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2895 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2896 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2897 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2898 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2900 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2901 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2902 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2903 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2905 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]);
2906 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]);
2910 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]);
2911 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]);
2914 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2915 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2916 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2917 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2919 if (t->pantstexture)
2920 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2922 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2924 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2926 if (t->shirttexture)
2927 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2929 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2931 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2932 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2933 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2934 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2935 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2936 r_glsl_offsetmapping_scale.value*t->offsetscale,
2937 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2938 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2939 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2941 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2942 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2943 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2944 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2946 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2947 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2948 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2949 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2950 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2951 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2952 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2953 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2954 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2955 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2956 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2957 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2958 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2959 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2960 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2961 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2962 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2963 if (rsurfacepass == RSURFPASS_BACKGROUND)
2965 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2966 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2967 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2973 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2974 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2975 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2976 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2978 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2979 if (rsurface.rtlight)
2981 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2982 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2989 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2991 // select a permutation of the lighting shader appropriate to this
2992 // combination of texture, entity, light source, and fogging, only use the
2993 // minimum features necessary to avoid wasting rendering time in the
2994 // fragment shader on features that are not being used
2995 dpuint64 permutation = 0;
2996 unsigned int mode = 0;
2997 const float *lightcolorbase = rtlight->currentcolor;
2998 float ambientscale = rtlight->ambientscale;
2999 float diffusescale = rtlight->diffusescale;
3000 float specularscale = rtlight->specularscale;
3001 // this is the location of the light in view space
3002 vec3_t viewlightorigin;
3003 // this transforms from view space (camera) to light space (cubemap)
3004 matrix4x4_t viewtolight;
3005 matrix4x4_t lighttoview;
3006 float viewtolight16f[16];
3008 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3009 if (rtlight->currentcubemap != r_texture_whitecube)
3010 permutation |= SHADERPERMUTATION_CUBEFILTER;
3011 if (diffusescale > 0)
3012 permutation |= SHADERPERMUTATION_DIFFUSE;
3013 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3014 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3015 if (r_shadow_usingshadowmap2d)
3017 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3018 if (r_shadow_shadowmapvsdct)
3019 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3021 if (r_shadow_shadowmap2ddepthbuffer)
3022 permutation |= SHADERPERMUTATION_DEPTHRGB;
3024 if (vid.allowalphatocoverage)
3025 GL_AlphaToCoverage(false);
3026 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3027 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3028 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3029 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3030 switch(vid.renderpath)
3032 case RENDERPATH_D3D9:
3034 R_SetupShader_SetPermutationHLSL(mode, permutation);
3035 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3037 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3038 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3039 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3040 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3041 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3042 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);
3043 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3046 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3047 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3048 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3049 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3050 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3053 case RENDERPATH_D3D10:
3054 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056 case RENDERPATH_D3D11:
3057 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3059 case RENDERPATH_GL20:
3060 case RENDERPATH_GLES2:
3061 R_SetupShader_SetPermutationGLSL(mode, permutation);
3062 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3063 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3064 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3065 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3066 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3067 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]);
3068 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]);
3069 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);
3070 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]);
3071 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3073 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3074 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3075 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3076 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3077 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3079 case RENDERPATH_GL11:
3080 case RENDERPATH_GL13:
3081 case RENDERPATH_GLES1:
3083 case RENDERPATH_SOFT:
3084 R_SetupShader_SetPermutationGLSL(mode, permutation);
3085 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3086 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3087 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3088 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3089 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3090 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]);
3091 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]);
3092 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);
3093 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3094 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3096 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3097 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3098 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3099 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3100 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3105 #define SKINFRAME_HASH 1024
3109 unsigned int loadsequence; // incremented each level change
3110 memexpandablearray_t array;
3111 skinframe_t *hash[SKINFRAME_HASH];
3114 r_skinframe_t r_skinframe;
3116 void R_SkinFrame_PrepareForPurge(void)
3118 r_skinframe.loadsequence++;
3119 // wrap it without hitting zero
3120 if (r_skinframe.loadsequence >= 200)
3121 r_skinframe.loadsequence = 1;
3124 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3128 // mark the skinframe as used for the purging code
3129 skinframe->loadsequence = r_skinframe.loadsequence;
3132 void R_SkinFrame_Purge(void)
3136 for (i = 0;i < SKINFRAME_HASH;i++)
3138 for (s = r_skinframe.hash[i];s;s = s->next)
3140 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3142 if (s->merged == s->base)
3144 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3145 R_PurgeTexture(s->stain );s->stain = NULL;
3146 R_PurgeTexture(s->merged);s->merged = NULL;
3147 R_PurgeTexture(s->base );s->base = NULL;
3148 R_PurgeTexture(s->pants );s->pants = NULL;
3149 R_PurgeTexture(s->shirt );s->shirt = NULL;
3150 R_PurgeTexture(s->nmap );s->nmap = NULL;
3151 R_PurgeTexture(s->gloss );s->gloss = NULL;
3152 R_PurgeTexture(s->glow );s->glow = NULL;
3153 R_PurgeTexture(s->fog );s->fog = NULL;
3154 R_PurgeTexture(s->reflect);s->reflect = NULL;
3155 s->loadsequence = 0;
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)))
3198 rtexture_t *dyntexture;
3199 // check whether its a dynamic texture
3200 dyntexture = CL_GetDynTexture( basename );
3201 if (!add && !dyntexture)
3203 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3204 memset(item, 0, sizeof(*item));
3205 strlcpy(item->basename, basename, sizeof(item->basename));
3206 item->base = dyntexture; // either NULL or dyntexture handle
3207 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3208 item->comparewidth = comparewidth;
3209 item->compareheight = compareheight;
3210 item->comparecrc = comparecrc;
3211 item->next = r_skinframe.hash[hashindex];
3212 r_skinframe.hash[hashindex] = item;
3214 else if (textureflags & TEXF_FORCE_RELOAD)
3216 rtexture_t *dyntexture;
3217 // check whether its a dynamic texture
3218 dyntexture = CL_GetDynTexture( basename );
3219 if (!add && !dyntexture)
3221 if (item->merged == item->base)
3222 item->merged = NULL;
3223 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3224 R_PurgeTexture(item->stain );item->stain = NULL;
3225 R_PurgeTexture(item->merged);item->merged = NULL;
3226 R_PurgeTexture(item->base );item->base = NULL;
3227 R_PurgeTexture(item->pants );item->pants = NULL;
3228 R_PurgeTexture(item->shirt );item->shirt = NULL;
3229 R_PurgeTexture(item->nmap );item->nmap = NULL;
3230 R_PurgeTexture(item->gloss );item->gloss = NULL;
3231 R_PurgeTexture(item->glow );item->glow = NULL;
3232 R_PurgeTexture(item->fog );item->fog = NULL;
3233 R_PurgeTexture(item->reflect);item->reflect = NULL;
3234 item->loadsequence = 0;
3236 else if( item->base == NULL )
3238 rtexture_t *dyntexture;
3239 // check whether its a dynamic texture
3240 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3241 dyntexture = CL_GetDynTexture( basename );
3242 item->base = dyntexture; // either NULL or dyntexture handle
3245 R_SkinFrame_MarkUsed(item);
3249 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3251 unsigned long long avgcolor[5], wsum; \
3259 for(pix = 0; pix < cnt; ++pix) \
3262 for(comp = 0; comp < 3; ++comp) \
3264 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3267 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3269 for(comp = 0; comp < 3; ++comp) \
3270 avgcolor[comp] += getpixel * w; \
3273 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3274 avgcolor[4] += getpixel; \
3276 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3278 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3279 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3280 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3281 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3284 extern cvar_t gl_picmip;
3285 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3288 unsigned char *pixels;
3289 unsigned char *bumppixels;
3290 unsigned char *basepixels = NULL;
3291 int basepixels_width = 0;
3292 int basepixels_height = 0;
3293 skinframe_t *skinframe;
3294 rtexture_t *ddsbase = NULL;
3295 qboolean ddshasalpha = false;
3296 float ddsavgcolor[4];
3297 char basename[MAX_QPATH];
3298 int miplevel = R_PicmipForFlags(textureflags);
3299 int savemiplevel = miplevel;
3303 if (cls.state == ca_dedicated)
3306 // return an existing skinframe if already loaded
3307 // if loading of the first image fails, don't make a new skinframe as it
3308 // would cause all future lookups of this to be missing
3309 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3310 if (skinframe && skinframe->base)
3313 Image_StripImageExtension(name, basename, sizeof(basename));
3315 // check for DDS texture file first
3316 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3318 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3319 if (basepixels == NULL)
3323 // FIXME handle miplevel
3325 if (developer_loading.integer)
3326 Con_Printf("loading skin \"%s\"\n", name);
3328 // we've got some pixels to store, so really allocate this new texture now
3330 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3331 textureflags &= ~TEXF_FORCE_RELOAD;
3332 skinframe->stain = NULL;
3333 skinframe->merged = NULL;
3334 skinframe->base = NULL;
3335 skinframe->pants = NULL;
3336 skinframe->shirt = NULL;
3337 skinframe->nmap = NULL;
3338 skinframe->gloss = NULL;
3339 skinframe->glow = NULL;
3340 skinframe->fog = NULL;
3341 skinframe->reflect = NULL;
3342 skinframe->hasalpha = false;
3343 // we could store the q2animname here too
3347 skinframe->base = ddsbase;
3348 skinframe->hasalpha = ddshasalpha;
3349 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3350 if (r_loadfog && skinframe->hasalpha)
3351 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);
3352 //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]);
3356 basepixels_width = image_width;
3357 basepixels_height = image_height;
3358 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);
3359 if (textureflags & TEXF_ALPHA)
3361 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3363 if (basepixels[j] < 255)
3365 skinframe->hasalpha = true;
3369 if (r_loadfog && skinframe->hasalpha)
3371 // has transparent pixels
3372 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3373 for (j = 0;j < image_width * image_height * 4;j += 4)
3378 pixels[j+3] = basepixels[j+3];
3380 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);
3384 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3386 //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]);
3387 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3388 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3389 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3390 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3396 mymiplevel = savemiplevel;
3397 if (r_loadnormalmap)
3398 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);
3399 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3402 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3403 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3404 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3407 // _norm is the name used by tenebrae and has been adopted as standard
3408 if (r_loadnormalmap && skinframe->nmap == NULL)
3410 mymiplevel = savemiplevel;
3411 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3413 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);
3417 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3419 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3420 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3421 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);
3423 Mem_Free(bumppixels);
3425 else if (r_shadow_bumpscale_basetexture.value > 0)
3427 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3428 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3429 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);
3433 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3434 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3438 // _luma is supported only for tenebrae compatibility
3439 // _glow is the preferred name
3440 mymiplevel = savemiplevel;
3441 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))))
3443 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);
3445 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3446 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3448 Mem_Free(pixels);pixels = NULL;
3451 mymiplevel = savemiplevel;
3452 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3454 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);
3456 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3457 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3463 mymiplevel = savemiplevel;
3464 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3466 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);
3468 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3469 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3475 mymiplevel = savemiplevel;
3476 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3478 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);
3480 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3481 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3487 mymiplevel = savemiplevel;
3488 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3490 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);
3492 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3493 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3500 Mem_Free(basepixels);
3505 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3506 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3509 skinframe_t *skinframe;
3512 if (cls.state == ca_dedicated)
3515 // if already loaded just return it, otherwise make a new skinframe
3516 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3517 if (skinframe->base)
3519 textureflags &= ~TEXF_FORCE_RELOAD;
3521 skinframe->stain = NULL;
3522 skinframe->merged = NULL;
3523 skinframe->base = NULL;
3524 skinframe->pants = NULL;
3525 skinframe->shirt = NULL;
3526 skinframe->nmap = NULL;
3527 skinframe->gloss = NULL;
3528 skinframe->glow = NULL;
3529 skinframe->fog = NULL;
3530 skinframe->reflect = NULL;
3531 skinframe->hasalpha = false;
3533 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3537 if (developer_loading.integer)
3538 Con_Printf("loading 32bit skin \"%s\"\n", name);
3540 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3542 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3543 unsigned char *b = a + width * height * 4;
3544 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3545 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);
3548 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3549 if (textureflags & TEXF_ALPHA)
3551 for (i = 3;i < width * height * 4;i += 4)
3553 if (skindata[i] < 255)
3555 skinframe->hasalpha = true;
3559 if (r_loadfog && skinframe->hasalpha)
3561 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3562 memcpy(fogpixels, skindata, width * height * 4);
3563 for (i = 0;i < width * height * 4;i += 4)
3564 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3565 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3566 Mem_Free(fogpixels);
3570 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3571 //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]);
3576 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3580 skinframe_t *skinframe;
3582 if (cls.state == ca_dedicated)
3585 // if already loaded just return it, otherwise make a new skinframe
3586 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3587 if (skinframe->base)
3589 //textureflags &= ~TEXF_FORCE_RELOAD;
3591 skinframe->stain = NULL;
3592 skinframe->merged = NULL;
3593 skinframe->base = NULL;
3594 skinframe->pants = NULL;
3595 skinframe->shirt = NULL;
3596 skinframe->nmap = NULL;
3597 skinframe->gloss = NULL;
3598 skinframe->glow = NULL;
3599 skinframe->fog = NULL;
3600 skinframe->reflect = NULL;
3601 skinframe->hasalpha = false;
3603 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3607 if (developer_loading.integer)
3608 Con_Printf("loading quake skin \"%s\"\n", name);
3610 // 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)
3611 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3612 memcpy(skinframe->qpixels, skindata, width*height);
3613 skinframe->qwidth = width;
3614 skinframe->qheight = height;
3617 for (i = 0;i < width * height;i++)
3618 featuresmask |= palette_featureflags[skindata[i]];
3620 skinframe->hasalpha = false;
3623 skinframe->hasalpha = true;
3624 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3625 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3626 skinframe->qgeneratemerged = true;
3627 skinframe->qgeneratebase = skinframe->qhascolormapping;
3628 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3630 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3631 //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]);
3636 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3640 unsigned char *skindata;
3643 if (!skinframe->qpixels)
3646 if (!skinframe->qhascolormapping)
3647 colormapped = false;
3651 if (!skinframe->qgeneratebase)
3656 if (!skinframe->qgeneratemerged)
3660 width = skinframe->qwidth;
3661 height = skinframe->qheight;
3662 skindata = skinframe->qpixels;
3664 if (skinframe->qgeneratenmap)
3666 unsigned char *a, *b;
3667 skinframe->qgeneratenmap = false;
3668 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3669 b = a + width * height * 4;
3670 // use either a custom palette or the quake palette
3671 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3672 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3673 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);
3677 if (skinframe->qgenerateglow)
3679 skinframe->qgenerateglow = false;
3680 if (skinframe->hasalpha) // fence textures
3681 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
3683 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
3688 skinframe->qgeneratebase = false;
3689 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);
3690 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);
3691 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);
3695 skinframe->qgeneratemerged = false;
3696 if (skinframe->hasalpha) // fence textures
3697 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);
3699 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);
3702 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3704 Mem_Free(skinframe->qpixels);
3705 skinframe->qpixels = NULL;
3709 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)
3712 skinframe_t *skinframe;
3715 if (cls.state == ca_dedicated)
3718 // if already loaded just return it, otherwise make a new skinframe
3719 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3720 if (skinframe->base)
3722 textureflags &= ~TEXF_FORCE_RELOAD;
3724 skinframe->stain = NULL;
3725 skinframe->merged = NULL;
3726 skinframe->base = NULL;
3727 skinframe->pants = NULL;
3728 skinframe->shirt = NULL;
3729 skinframe->nmap = NULL;
3730 skinframe->gloss = NULL;
3731 skinframe->glow = NULL;
3732 skinframe->fog = NULL;
3733 skinframe->reflect = NULL;
3734 skinframe->hasalpha = false;
3736 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3740 if (developer_loading.integer)
3741 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3743 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3744 if (textureflags & TEXF_ALPHA)
3746 for (i = 0;i < width * height;i++)
3748 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3750 skinframe->hasalpha = true;
3754 if (r_loadfog && skinframe->hasalpha)
3755 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3758 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3759 //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]);
3764 skinframe_t *R_SkinFrame_LoadMissing(void)
3766 skinframe_t *skinframe;
3768 if (cls.state == ca_dedicated)
3771 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3772 skinframe->stain = NULL;
3773 skinframe->merged = NULL;
3774 skinframe->base = NULL;
3775 skinframe->pants = NULL;
3776 skinframe->shirt = NULL;
3777 skinframe->nmap = NULL;
3778 skinframe->gloss = NULL;
3779 skinframe->glow = NULL;
3780 skinframe->fog = NULL;
3781 skinframe->reflect = NULL;
3782 skinframe->hasalpha = false;
3784 skinframe->avgcolor[0] = rand() / RAND_MAX;
3785 skinframe->avgcolor[1] = rand() / RAND_MAX;
3786 skinframe->avgcolor[2] = rand() / RAND_MAX;
3787 skinframe->avgcolor[3] = 1;
3792 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3793 typedef struct suffixinfo_s
3796 qboolean flipx, flipy, flipdiagonal;
3799 static suffixinfo_t suffix[3][6] =
3802 {"px", false, false, false},
3803 {"nx", false, false, false},
3804 {"py", false, false, false},
3805 {"ny", false, false, false},
3806 {"pz", false, false, false},
3807 {"nz", false, false, false}
3810 {"posx", false, false, false},
3811 {"negx", false, false, false},
3812 {"posy", false, false, false},
3813 {"negy", false, false, false},
3814 {"posz", false, false, false},
3815 {"negz", false, false, false}
3818 {"rt", true, false, true},
3819 {"lf", false, true, true},
3820 {"ft", true, true, false},
3821 {"bk", false, false, false},
3822 {"up", true, false, true},
3823 {"dn", true, false, true}
3827 static int componentorder[4] = {0, 1, 2, 3};
3829 static rtexture_t *R_LoadCubemap(const char *basename)
3831 int i, j, cubemapsize;
3832 unsigned char *cubemappixels, *image_buffer;
3833 rtexture_t *cubemaptexture;
3835 // must start 0 so the first loadimagepixels has no requested width/height
3837 cubemappixels = NULL;
3838 cubemaptexture = NULL;
3839 // keep trying different suffix groups (posx, px, rt) until one loads
3840 for (j = 0;j < 3 && !cubemappixels;j++)
3842 // load the 6 images in the suffix group
3843 for (i = 0;i < 6;i++)
3845 // generate an image name based on the base and and suffix
3846 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3848 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3850 // an image loaded, make sure width and height are equal
3851 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3853 // if this is the first image to load successfully, allocate the cubemap memory
3854 if (!cubemappixels && image_width >= 1)
3856 cubemapsize = image_width;
3857 // note this clears to black, so unavailable sides are black
3858 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3860 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3862 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);
3865 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3867 Mem_Free(image_buffer);
3871 // if a cubemap loaded, upload it
3874 if (developer_loading.integer)
3875 Con_Printf("loading cubemap \"%s\"\n", basename);
3877 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);
3878 Mem_Free(cubemappixels);
3882 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3883 if (developer_loading.integer)
3885 Con_Printf("(tried tried images ");
3886 for (j = 0;j < 3;j++)
3887 for (i = 0;i < 6;i++)
3888 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3889 Con_Print(" and was unable to find any of them).\n");
3892 return cubemaptexture;
3895 rtexture_t *R_GetCubemap(const char *basename)
3898 for (i = 0;i < r_texture_numcubemaps;i++)
3899 if (r_texture_cubemaps[i] != NULL)
3900 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3901 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3902 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3903 return r_texture_whitecube;
3904 r_texture_numcubemaps++;
3905 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3906 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3907 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3908 return r_texture_cubemaps[i]->texture;
3911 static void R_Main_FreeViewCache(void)
3913 if (r_refdef.viewcache.entityvisible)
3914 Mem_Free(r_refdef.viewcache.entityvisible);
3915 if (r_refdef.viewcache.world_pvsbits)
3916 Mem_Free(r_refdef.viewcache.world_pvsbits);
3917 if (r_refdef.viewcache.world_leafvisible)
3918 Mem_Free(r_refdef.viewcache.world_leafvisible);
3919 if (r_refdef.viewcache.world_surfacevisible)
3920 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3924 static void R_Main_ResizeViewCache(void)
3926 int numentities = r_refdef.scene.numentities;
3927 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3928 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3929 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3930 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3931 if (r_refdef.viewcache.maxentities < numentities)
3933 r_refdef.viewcache.maxentities = numentities;
3934 if (r_refdef.viewcache.entityvisible)
3935 Mem_Free(r_refdef.viewcache.entityvisible);
3936 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3938 if (r_refdef.viewcache.world_numclusters != numclusters)
3940 r_refdef.viewcache.world_numclusters = numclusters;
3941 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3942 if (r_refdef.viewcache.world_pvsbits)
3943 Mem_Free(r_refdef.viewcache.world_pvsbits);
3944 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3946 if (r_refdef.viewcache.world_numleafs != numleafs)
3948 r_refdef.viewcache.world_numleafs = numleafs;
3949 if (r_refdef.viewcache.world_leafvisible)
3950 Mem_Free(r_refdef.viewcache.world_leafvisible);
3951 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3953 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3955 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3956 if (r_refdef.viewcache.world_surfacevisible)
3957 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3958 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3962 extern rtexture_t *loadingscreentexture;
3963 static void gl_main_start(void)
3965 loadingscreentexture = NULL;
3966 r_texture_blanknormalmap = NULL;
3967 r_texture_white = NULL;
3968 r_texture_grey128 = NULL;
3969 r_texture_black = NULL;
3970 r_texture_whitecube = NULL;
3971 r_texture_normalizationcube = NULL;
3972 r_texture_fogattenuation = NULL;
3973 r_texture_fogheighttexture = NULL;
3974 r_texture_gammaramps = NULL;
3975 r_texture_numcubemaps = 0;
3976 r_uniformbufferalignment = 32;
3978 r_loaddds = r_texture_dds_load.integer != 0;
3979 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3981 switch(vid.renderpath)
3983 case RENDERPATH_GL20:
3984 case RENDERPATH_D3D9:
3985 case RENDERPATH_D3D10:
3986 case RENDERPATH_D3D11:
3987 case RENDERPATH_SOFT:
3988 case RENDERPATH_GLES2:
3989 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3990 Cvar_SetValueQuick(&gl_combine, 1);
3991 Cvar_SetValueQuick(&r_glsl, 1);
3992 r_loadnormalmap = true;
3995 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
3996 if (vid.support.arb_uniform_buffer_object)
3997 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4000 case RENDERPATH_GL13:
4001 case RENDERPATH_GLES1:
4002 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4003 Cvar_SetValueQuick(&gl_combine, 1);
4004 Cvar_SetValueQuick(&r_glsl, 0);
4005 r_loadnormalmap = false;
4006 r_loadgloss = false;
4009 case RENDERPATH_GL11:
4010 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4011 Cvar_SetValueQuick(&gl_combine, 0);
4012 Cvar_SetValueQuick(&r_glsl, 0);
4013 r_loadnormalmap = false;
4014 r_loadgloss = false;
4020 R_FrameData_Reset();
4021 R_BufferData_Reset();
4025 memset(r_queries, 0, sizeof(r_queries));
4027 r_qwskincache = NULL;
4028 r_qwskincache_size = 0;
4030 // due to caching of texture_t references, the collision cache must be reset
4031 Collision_Cache_Reset(true);
4033 // set up r_skinframe loading system for textures
4034 memset(&r_skinframe, 0, sizeof(r_skinframe));
4035 r_skinframe.loadsequence = 1;
4036 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4038 r_main_texturepool = R_AllocTexturePool();
4039 R_BuildBlankTextures();
4041 if (vid.support.arb_texture_cube_map)
4044 R_BuildNormalizationCube();
4046 r_texture_fogattenuation = NULL;
4047 r_texture_fogheighttexture = NULL;
4048 r_texture_gammaramps = NULL;
4049 //r_texture_fogintensity = NULL;
4050 memset(&r_fb, 0, sizeof(r_fb));
4051 r_glsl_permutation = NULL;
4052 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4053 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4055 r_hlsl_permutation = NULL;
4056 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4057 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4059 memset(&r_svbsp, 0, sizeof (r_svbsp));
4061 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4062 r_texture_numcubemaps = 0;
4064 r_refdef.fogmasktable_density = 0;
4067 // For Steelstorm Android
4068 // FIXME CACHE the program and reload
4069 // FIXME see possible combinations for SS:BR android
4070 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4071 R_SetupShader_SetPermutationGLSL(0, 12);
4072 R_SetupShader_SetPermutationGLSL(0, 13);
4073 R_SetupShader_SetPermutationGLSL(0, 8388621);
4074 R_SetupShader_SetPermutationGLSL(3, 0);
4075 R_SetupShader_SetPermutationGLSL(3, 2048);
4076 R_SetupShader_SetPermutationGLSL(5, 0);
4077 R_SetupShader_SetPermutationGLSL(5, 2);
4078 R_SetupShader_SetPermutationGLSL(5, 2048);
4079 R_SetupShader_SetPermutationGLSL(5, 8388608);
4080 R_SetupShader_SetPermutationGLSL(11, 1);
4081 R_SetupShader_SetPermutationGLSL(11, 2049);
4082 R_SetupShader_SetPermutationGLSL(11, 8193);
4083 R_SetupShader_SetPermutationGLSL(11, 10241);
4084 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4088 static void gl_main_shutdown(void)
4091 R_FrameData_Reset();
4092 R_BufferData_Reset();
4094 R_Main_FreeViewCache();
4096 switch(vid.renderpath)
4098 case RENDERPATH_GL11:
4099 case RENDERPATH_GL13:
4100 case RENDERPATH_GL20:
4101 case RENDERPATH_GLES1:
4102 case RENDERPATH_GLES2:
4103 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4105 qglDeleteQueriesARB(r_maxqueries, r_queries);
4108 case RENDERPATH_D3D9:
4109 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4111 case RENDERPATH_D3D10:
4112 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4114 case RENDERPATH_D3D11:
4115 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4117 case RENDERPATH_SOFT:
4123 memset(r_queries, 0, sizeof(r_queries));
4125 r_qwskincache = NULL;
4126 r_qwskincache_size = 0;
4128 // clear out the r_skinframe state
4129 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4130 memset(&r_skinframe, 0, sizeof(r_skinframe));
4133 Mem_Free(r_svbsp.nodes);
4134 memset(&r_svbsp, 0, sizeof (r_svbsp));
4135 R_FreeTexturePool(&r_main_texturepool);
4136 loadingscreentexture = NULL;
4137 r_texture_blanknormalmap = NULL;
4138 r_texture_white = NULL;
4139 r_texture_grey128 = NULL;
4140 r_texture_black = NULL;
4141 r_texture_whitecube = NULL;
4142 r_texture_normalizationcube = NULL;
4143 r_texture_fogattenuation = NULL;
4144 r_texture_fogheighttexture = NULL;
4145 r_texture_gammaramps = NULL;
4146 r_texture_numcubemaps = 0;
4147 //r_texture_fogintensity = NULL;
4148 memset(&r_fb, 0, sizeof(r_fb));
4151 r_glsl_permutation = NULL;
4152 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4153 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4155 r_hlsl_permutation = NULL;
4156 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4157 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4161 static void gl_main_newmap(void)
4163 // FIXME: move this code to client
4164 char *entities, entname[MAX_QPATH];
4166 Mem_Free(r_qwskincache);
4167 r_qwskincache = NULL;
4168 r_qwskincache_size = 0;
4171 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4172 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4174 CL_ParseEntityLump(entities);
4178 if (cl.worldmodel->brush.entities)
4179 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4181 R_Main_FreeViewCache();
4183 R_FrameData_Reset();
4184 R_BufferData_Reset();
4187 void GL_Main_Init(void)
4190 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4191 R_InitShaderModeInfo();
4193 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4194 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4195 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4196 if (gamemode == GAME_NEHAHRA)
4198 Cvar_RegisterVariable (&gl_fogenable);
4199 Cvar_RegisterVariable (&gl_fogdensity);
4200 Cvar_RegisterVariable (&gl_fogred);
4201 Cvar_RegisterVariable (&gl_foggreen);
4202 Cvar_RegisterVariable (&gl_fogblue);
4203 Cvar_RegisterVariable (&gl_fogstart);
4204 Cvar_RegisterVariable (&gl_fogend);
4205 Cvar_RegisterVariable (&gl_skyclip);
4207 Cvar_RegisterVariable(&r_motionblur);
4208 Cvar_RegisterVariable(&r_damageblur);
4209 Cvar_RegisterVariable(&r_motionblur_averaging);
4210 Cvar_RegisterVariable(&r_motionblur_randomize);
4211 Cvar_RegisterVariable(&r_motionblur_minblur);
4212 Cvar_RegisterVariable(&r_motionblur_maxblur);
4213 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4214 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4215 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4216 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4217 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4218 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4219 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4220 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4221 Cvar_RegisterVariable(&r_equalize_entities_by);
4222 Cvar_RegisterVariable(&r_equalize_entities_to);
4223 Cvar_RegisterVariable(&r_depthfirst);
4224 Cvar_RegisterVariable(&r_useinfinitefarclip);
4225 Cvar_RegisterVariable(&r_farclip_base);
4226 Cvar_RegisterVariable(&r_farclip_world);
4227 Cvar_RegisterVariable(&r_nearclip);
4228 Cvar_RegisterVariable(&r_deformvertexes);
4229 Cvar_RegisterVariable(&r_transparent);
4230 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4231 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4232 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4233 Cvar_RegisterVariable(&r_showoverdraw);
4234 Cvar_RegisterVariable(&r_showbboxes);
4235 Cvar_RegisterVariable(&r_showbboxes_client);
4236 Cvar_RegisterVariable(&r_showsurfaces);
4237 Cvar_RegisterVariable(&r_showtris);
4238 Cvar_RegisterVariable(&r_shownormals);
4239 Cvar_RegisterVariable(&r_showlighting);
4240 Cvar_RegisterVariable(&r_showshadowvolumes);
4241 Cvar_RegisterVariable(&r_showcollisionbrushes);
4242 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4243 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4244 Cvar_RegisterVariable(&r_showdisabledepthtest);
4245 Cvar_RegisterVariable(&r_drawportals);
4246 Cvar_RegisterVariable(&r_drawentities);
4247 Cvar_RegisterVariable(&r_draw2d);
4248 Cvar_RegisterVariable(&r_drawworld);
4249 Cvar_RegisterVariable(&r_cullentities_trace);
4250 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4251 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4252 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4253 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4254 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4255 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4256 Cvar_RegisterVariable(&r_sortentities);
4257 Cvar_RegisterVariable(&r_drawviewmodel);
4258 Cvar_RegisterVariable(&r_drawexteriormodel);
4259 Cvar_RegisterVariable(&r_speeds);
4260 Cvar_RegisterVariable(&r_fullbrights);
4261 Cvar_RegisterVariable(&r_wateralpha);
4262 Cvar_RegisterVariable(&r_dynamic);
4263 Cvar_RegisterVariable(&r_fakelight);
4264 Cvar_RegisterVariable(&r_fakelight_intensity);
4265 Cvar_RegisterVariable(&r_fullbright_directed);
4266 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4267 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4268 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4269 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4270 Cvar_RegisterVariable(&r_fullbright);
4271 Cvar_RegisterVariable(&r_shadows);
4272 Cvar_RegisterVariable(&r_shadows_darken);
4273 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4274 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4275 Cvar_RegisterVariable(&r_shadows_throwdistance);
4276 Cvar_RegisterVariable(&r_shadows_throwdirection);
4277 Cvar_RegisterVariable(&r_shadows_focus);
4278 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4279 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4280 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4281 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4282 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4283 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4284 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4285 Cvar_RegisterVariable(&r_fog_exp2);
4286 Cvar_RegisterVariable(&r_fog_clear);
4287 Cvar_RegisterVariable(&r_drawfog);
4288 Cvar_RegisterVariable(&r_transparentdepthmasking);
4289 Cvar_RegisterVariable(&r_transparent_sortmindist);
4290 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4291 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4292 Cvar_RegisterVariable(&r_texture_dds_load);
4293 Cvar_RegisterVariable(&r_texture_dds_save);
4294 Cvar_RegisterVariable(&r_textureunits);
4295 Cvar_RegisterVariable(&gl_combine);
4296 Cvar_RegisterVariable(&r_usedepthtextures);
4297 Cvar_RegisterVariable(&r_viewfbo);
4298 Cvar_RegisterVariable(&r_viewscale);
4299 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4300 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4301 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4302 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4303 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4304 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4305 Cvar_RegisterVariable(&r_glsl);
4306 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4307 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4308 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4309 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4310 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4311 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4312 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4313 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4314 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4315 Cvar_RegisterVariable(&r_glsl_postprocess);
4316 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4317 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4318 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4319 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4320 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4321 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4322 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4323 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4324 Cvar_RegisterVariable(&r_celshading);
4325 Cvar_RegisterVariable(&r_celoutlines);
4327 Cvar_RegisterVariable(&r_water);
4328 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4329 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4330 Cvar_RegisterVariable(&r_water_clippingplanebias);
4331 Cvar_RegisterVariable(&r_water_refractdistort);
4332 Cvar_RegisterVariable(&r_water_reflectdistort);
4333 Cvar_RegisterVariable(&r_water_scissormode);
4334 Cvar_RegisterVariable(&r_water_lowquality);
4335 Cvar_RegisterVariable(&r_water_hideplayer);
4336 Cvar_RegisterVariable(&r_water_fbo);
4338 Cvar_RegisterVariable(&r_lerpsprites);
4339 Cvar_RegisterVariable(&r_lerpmodels);
4340 Cvar_RegisterVariable(&r_lerplightstyles);
4341 Cvar_RegisterVariable(&r_waterscroll);
4342 Cvar_RegisterVariable(&r_bloom);
4343 Cvar_RegisterVariable(&r_bloom_colorscale);
4344 Cvar_RegisterVariable(&r_bloom_brighten);
4345 Cvar_RegisterVariable(&r_bloom_blur);
4346 Cvar_RegisterVariable(&r_bloom_resolution);
4347 Cvar_RegisterVariable(&r_bloom_colorexponent);
4348 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4349 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4350 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4351 Cvar_RegisterVariable(&r_hdr_glowintensity);
4352 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4353 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4354 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4355 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4356 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4357 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4358 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4359 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4360 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4361 Cvar_RegisterVariable(&developer_texturelogging);
4362 Cvar_RegisterVariable(&gl_lightmaps);
4363 Cvar_RegisterVariable(&r_test);
4364 Cvar_RegisterVariable(&r_batch_multidraw);
4365 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4366 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4367 Cvar_RegisterVariable(&r_glsl_skeletal);
4368 Cvar_RegisterVariable(&r_glsl_saturation);
4369 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4370 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4371 Cvar_RegisterVariable(&r_framedatasize);
4372 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4373 Cvar_RegisterVariable(&r_buffermegs[i]);
4374 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4375 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4376 Cvar_SetValue("r_fullbrights", 0);
4377 #ifdef DP_MOBILETOUCH
4378 // GLES devices have terrible depth precision in general, so...
4379 Cvar_SetValueQuick(&r_nearclip, 4);
4380 Cvar_SetValueQuick(&r_farclip_base, 4096);
4381 Cvar_SetValueQuick(&r_farclip_world, 0);
4382 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4384 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4387 void Render_Init(void)
4400 R_LightningBeams_Init();
4410 extern char *ENGINE_EXTENSIONS;
4413 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4414 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4415 gl_version = (const char *)qglGetString(GL_VERSION);
4416 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4420 if (!gl_platformextensions)
4421 gl_platformextensions = "";
4423 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4424 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4425 Con_Printf("GL_VERSION: %s\n", gl_version);
4426 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4427 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4429 VID_CheckExtensions();
4431 // LordHavoc: report supported extensions
4433 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4435 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4438 // clear to black (loading plaque will be seen over this)
4439 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4443 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4447 if (r_trippy.integer)
4449 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4451 p = r_refdef.view.frustum + i;
4456 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4460 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4464 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4468 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4472 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4476 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4480 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4484 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4492 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4496 if (r_trippy.integer)
4498 for (i = 0;i < numplanes;i++)
4505 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4509 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4513 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4517 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4521 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4525 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4529 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4533 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4541 //==================================================================================
4543 // LordHavoc: this stores temporary data used within the same frame
4545 typedef struct r_framedata_mem_s
4547 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4548 size_t size; // how much usable space
4549 size_t current; // how much space in use
4550 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4551 size_t wantedsize; // how much space was allocated
4552 unsigned char *data; // start of real data (16byte aligned)
4556 static r_framedata_mem_t *r_framedata_mem;
4558 void R_FrameData_Reset(void)
4560 while (r_framedata_mem)
4562 r_framedata_mem_t *next = r_framedata_mem->purge;
4563 Mem_Free(r_framedata_mem);
4564 r_framedata_mem = next;
4568 static void R_FrameData_Resize(qboolean mustgrow)
4571 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4572 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4573 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4575 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4576 newmem->wantedsize = wantedsize;
4577 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4578 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4579 newmem->current = 0;
4581 newmem->purge = r_framedata_mem;
4582 r_framedata_mem = newmem;
4586 void R_FrameData_NewFrame(void)
4588 R_FrameData_Resize(false);
4589 if (!r_framedata_mem)
4591 // if we ran out of space on the last frame, free the old memory now
4592 while (r_framedata_mem->purge)
4594 // repeatedly remove the second item in the list, leaving only head
4595 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4596 Mem_Free(r_framedata_mem->purge);
4597 r_framedata_mem->purge = next;
4599 // reset the current mem pointer
4600 r_framedata_mem->current = 0;
4601 r_framedata_mem->mark = 0;
4604 void *R_FrameData_Alloc(size_t size)
4609 // align to 16 byte boundary - the data pointer is already aligned, so we
4610 // only need to ensure the size of every allocation is also aligned
4611 size = (size + 15) & ~15;
4613 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4615 // emergency - we ran out of space, allocate more memory
4616 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4617 newvalue = r_framedatasize.value * 2.0f;
4618 // 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
4619 if (sizeof(size_t) >= 8)
4620 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4622 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4623 // this might not be a growing it, but we'll allocate another buffer every time
4624 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4625 R_FrameData_Resize(true);
4628 data = r_framedata_mem->data + r_framedata_mem->current;
4629 r_framedata_mem->current += size;
4631 // count the usage for stats
4632 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4633 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4635 return (void *)data;
4638 void *R_FrameData_Store(size_t size, void *data)
4640 void *d = R_FrameData_Alloc(size);
4642 memcpy(d, data, size);
4646 void R_FrameData_SetMark(void)
4648 if (!r_framedata_mem)
4650 r_framedata_mem->mark = r_framedata_mem->current;
4653 void R_FrameData_ReturnToMark(void)
4655 if (!r_framedata_mem)
4657 r_framedata_mem->current = r_framedata_mem->mark;
4660 //==================================================================================
4662 // avoid reusing the same buffer objects on consecutive frames
4663 #define R_BUFFERDATA_CYCLE 3
4665 typedef struct r_bufferdata_buffer_s
4667 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4668 size_t size; // how much usable space
4669 size_t current; // how much space in use
4670 r_meshbuffer_t *buffer; // the buffer itself
4672 r_bufferdata_buffer_t;
4674 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4675 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4677 /// frees all dynamic buffers
4678 void R_BufferData_Reset(void)
4681 r_bufferdata_buffer_t **p, *mem;
4682 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4684 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4687 p = &r_bufferdata_buffer[cycle][type];
4693 R_Mesh_DestroyMeshBuffer(mem->buffer);
4700 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4701 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4703 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4705 float newvalue = r_buffermegs[type].value;
4707 // increase the cvar if we have to (but only if we already have a mem)
4708 if (mustgrow && mem)
4710 newvalue = bound(0.25f, newvalue, 256.0f);
4711 while (newvalue * 1024*1024 < minsize)
4714 // clamp the cvar to valid range
4715 newvalue = bound(0.25f, newvalue, 256.0f);
4716 if (r_buffermegs[type].value != newvalue)
4717 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4719 // calculate size in bytes
4720 size = (size_t)(newvalue * 1024*1024);
4721 size = bound(131072, size, 256*1024*1024);
4723 // allocate a new buffer if the size is different (purge old one later)
4724 // or if we were told we must grow the buffer
4725 if (!mem || mem->size != size || mustgrow)
4727 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4730 if (type == R_BUFFERDATA_VERTEX)
4731 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4732 else if (type == R_BUFFERDATA_INDEX16)
4733 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4734 else if (type == R_BUFFERDATA_INDEX32)
4735 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4736 else if (type == R_BUFFERDATA_UNIFORM)
4737 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4738 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4739 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4743 void R_BufferData_NewFrame(void)
4746 r_bufferdata_buffer_t **p, *mem;
4747 // cycle to the next frame's buffers
4748 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4749 // if we ran out of space on the last time we used these buffers, free the old memory now
4750 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4752 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4754 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4755 // free all but the head buffer, this is how we recycle obsolete
4756 // buffers after they are no longer in use
4757 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4763 R_Mesh_DestroyMeshBuffer(mem->buffer);
4766 // reset the current offset
4767 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4772 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4774 r_bufferdata_buffer_t *mem;
4778 *returnbufferoffset = 0;
4780 // align size to a byte boundary appropriate for the buffer type, this
4781 // makes all allocations have aligned start offsets
4782 if (type == R_BUFFERDATA_UNIFORM)
4783 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4785 padsize = (datasize + 15) & ~15;
4787 // if we ran out of space in this buffer we must allocate a new one
4788 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)
4789 R_BufferData_Resize(type, true, padsize);
4791 // if the resize did not give us enough memory, fail
4792 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)
4793 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4795 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4796 offset = (int)mem->current;
4797 mem->current += padsize;
4799 // upload the data to the buffer at the chosen offset
4801 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4802 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4804 // count the usage for stats
4805 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4806 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4808 // return the buffer offset
4809 *returnbufferoffset = offset;
4814 //==================================================================================
4816 // LordHavoc: animcache originally written by Echon, rewritten since then
4819 * Animation cache prevents re-generating mesh data for an animated model
4820 * multiple times in one frame for lighting, shadowing, reflections, etc.
4823 void R_AnimCache_Free(void)
4827 void R_AnimCache_ClearCache(void)
4830 entity_render_t *ent;
4832 for (i = 0;i < r_refdef.scene.numentities;i++)
4834 ent = r_refdef.scene.entities[i];
4835 ent->animcache_vertex3f = NULL;
4836 ent->animcache_vertex3f_vertexbuffer = NULL;
4837 ent->animcache_vertex3f_bufferoffset = 0;
4838 ent->animcache_normal3f = NULL;
4839 ent->animcache_normal3f_vertexbuffer = NULL;
4840 ent->animcache_normal3f_bufferoffset = 0;
4841 ent->animcache_svector3f = NULL;
4842 ent->animcache_svector3f_vertexbuffer = NULL;
4843 ent->animcache_svector3f_bufferoffset = 0;
4844 ent->animcache_tvector3f = NULL;
4845 ent->animcache_tvector3f_vertexbuffer = NULL;
4846 ent->animcache_tvector3f_bufferoffset = 0;
4847 ent->animcache_vertexmesh = NULL;
4848 ent->animcache_vertexmesh_vertexbuffer = NULL;
4849 ent->animcache_vertexmesh_bufferoffset = 0;
4850 ent->animcache_skeletaltransform3x4 = NULL;
4851 ent->animcache_skeletaltransform3x4buffer = NULL;
4852 ent->animcache_skeletaltransform3x4offset = 0;
4853 ent->animcache_skeletaltransform3x4size = 0;
4857 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4861 // check if we need the meshbuffers
4862 if (!vid.useinterleavedarrays)
4865 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4866 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4867 // TODO: upload vertexbuffer?
4868 if (ent->animcache_vertexmesh)
4870 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4871 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4872 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4873 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4874 for (i = 0;i < numvertices;i++)
4875 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4876 if (ent->animcache_svector3f)
4877 for (i = 0;i < numvertices;i++)
4878 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4879 if (ent->animcache_tvector3f)
4880 for (i = 0;i < numvertices;i++)
4881 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4882 if (ent->animcache_normal3f)
4883 for (i = 0;i < numvertices;i++)
4884 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4888 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4890 dp_model_t *model = ent->model;
4893 // see if this ent is worth caching
4894 if (!model || !model->Draw || !model->AnimateVertices)
4896 // nothing to cache if it contains no animations and has no skeleton
4897 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4899 // see if it is already cached for gpuskeletal
4900 if (ent->animcache_skeletaltransform3x4)
4902 // see if it is already cached as a mesh
4903 if (ent->animcache_vertex3f)
4905 // check if we need to add normals or tangents
4906 if (ent->animcache_normal3f)
4907 wantnormals = false;
4908 if (ent->animcache_svector3f)
4909 wanttangents = false;
4910 if (!wantnormals && !wanttangents)
4914 // check which kind of cache we need to generate
4915 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4917 // cache the skeleton so the vertex shader can use it
4918 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4919 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4920 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4921 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4922 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4923 // note: this can fail if the buffer is at the grow limit
4924 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4925 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4927 else if (ent->animcache_vertex3f)
4929 // mesh was already cached but we may need to add normals/tangents
4930 // (this only happens with multiple views, reflections, cameras, etc)
4931 if (wantnormals || wanttangents)
4933 numvertices = model->surfmesh.num_vertices;
4935 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4938 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4939 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4941 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4942 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4943 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4944 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4945 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4950 // generate mesh cache
4951 numvertices = model->surfmesh.num_vertices;
4952 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4954 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4957 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4958 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4960 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4961 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4962 if (wantnormals || wanttangents)
4964 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4965 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4966 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4968 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4969 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4970 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4975 void R_AnimCache_CacheVisibleEntities(void)
4978 qboolean wantnormals = true;
4979 qboolean wanttangents = !r_showsurfaces.integer;
4981 switch(vid.renderpath)
4983 case RENDERPATH_GL20:
4984 case RENDERPATH_D3D9:
4985 case RENDERPATH_D3D10:
4986 case RENDERPATH_D3D11:
4987 case RENDERPATH_GLES2:
4989 case RENDERPATH_GL11:
4990 case RENDERPATH_GL13:
4991 case RENDERPATH_GLES1:
4992 wanttangents = false;
4994 case RENDERPATH_SOFT:
4998 if (r_shownormals.integer)
4999 wanttangents = wantnormals = true;
5001 // TODO: thread this
5002 // NOTE: R_PrepareRTLights() also caches entities
5004 for (i = 0;i < r_refdef.scene.numentities;i++)
5005 if (r_refdef.viewcache.entityvisible[i])
5006 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5009 //==================================================================================
5011 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5014 vec3_t eyemins, eyemaxs;
5015 vec3_t boxmins, boxmaxs;
5018 dp_model_t *model = r_refdef.scene.worldmodel;
5019 static vec3_t positions[] = {
5020 { 0.5f, 0.5f, 0.5f },
5021 { 0.0f, 0.0f, 0.0f },
5022 { 0.0f, 0.0f, 1.0f },
5023 { 0.0f, 1.0f, 0.0f },
5024 { 0.0f, 1.0f, 1.0f },
5025 { 1.0f, 0.0f, 0.0f },
5026 { 1.0f, 0.0f, 1.0f },
5027 { 1.0f, 1.0f, 0.0f },
5028 { 1.0f, 1.0f, 1.0f },
5031 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5035 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5036 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5039 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5042 // expand the eye box a little
5043 eyemins[0] = eye[0] - eyejitter;
5044 eyemaxs[0] = eye[0] + eyejitter;
5045 eyemins[1] = eye[1] - eyejitter;
5046 eyemaxs[1] = eye[1] + eyejitter;
5047 eyemins[2] = eye[2] - eyejitter;
5048 eyemaxs[2] = eye[2] + eyejitter;
5049 // expand the box a little
5050 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5051 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5052 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5053 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5054 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5055 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5057 // return true if eye overlaps enlarged box
5058 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5061 // try specific positions in the box first - note that these can be cached
5062 if (r_cullentities_trace_entityocclusion.integer)
5064 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5066 VectorCopy(eye, start);
5067 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5068 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5069 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5070 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5071 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5072 // not picky - if the trace ended anywhere in the box we're good
5073 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5077 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5080 // try various random positions
5081 for (i = 0; i < numsamples; i++)
5083 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5084 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5085 if (r_cullentities_trace_entityocclusion.integer)
5087 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5088 // not picky - if the trace ended anywhere in the box we're good
5089 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5092 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5100 static void R_View_UpdateEntityVisible (void)
5105 entity_render_t *ent;
5107 if (r_refdef.envmap || r_fb.water.hideplayer)
5108 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5109 else if (chase_active.integer || r_fb.water.renderingscene)
5110 renderimask = RENDER_VIEWMODEL;
5112 renderimask = RENDER_EXTERIORMODEL;
5113 if (!r_drawviewmodel.integer)
5114 renderimask |= RENDER_VIEWMODEL;
5115 if (!r_drawexteriormodel.integer)
5116 renderimask |= RENDER_EXTERIORMODEL;
5117 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5118 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5120 // worldmodel can check visibility
5121 for (i = 0;i < r_refdef.scene.numentities;i++)
5123 ent = r_refdef.scene.entities[i];
5124 if (!(ent->flags & renderimask))
5125 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)))
5126 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))
5127 r_refdef.viewcache.entityvisible[i] = true;
5132 // no worldmodel or it can't check visibility
5133 for (i = 0;i < r_refdef.scene.numentities;i++)
5135 ent = r_refdef.scene.entities[i];
5136 if (!(ent->flags & renderimask))
5137 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)))
5138 r_refdef.viewcache.entityvisible[i] = true;
5141 if (r_cullentities_trace.integer)
5143 for (i = 0;i < r_refdef.scene.numentities;i++)
5145 if (!r_refdef.viewcache.entityvisible[i])
5147 ent = r_refdef.scene.entities[i];
5148 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5150 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5151 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5152 ent->last_trace_visibility = realtime;
5153 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5154 r_refdef.viewcache.entityvisible[i] = 0;
5160 /// only used if skyrendermasked, and normally returns false
5161 static int R_DrawBrushModelsSky (void)
5164 entity_render_t *ent;
5167 for (i = 0;i < r_refdef.scene.numentities;i++)
5169 if (!r_refdef.viewcache.entityvisible[i])
5171 ent = r_refdef.scene.entities[i];
5172 if (!ent->model || !ent->model->DrawSky)
5174 ent->model->DrawSky(ent);
5180 static void R_DrawNoModel(entity_render_t *ent);
5181 static void R_DrawModels(void)
5184 entity_render_t *ent;
5186 for (i = 0;i < r_refdef.scene.numentities;i++)
5188 if (!r_refdef.viewcache.entityvisible[i])
5190 ent = r_refdef.scene.entities[i];
5191 r_refdef.stats[r_stat_entities]++;
5193 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5196 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5197 Con_Printf("R_DrawModels\n");
5198 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]);
5199 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);
5200 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);
5203 if (ent->model && ent->model->Draw != NULL)
5204 ent->model->Draw(ent);
5210 static void R_DrawModelsDepth(void)
5213 entity_render_t *ent;
5215 for (i = 0;i < r_refdef.scene.numentities;i++)
5217 if (!r_refdef.viewcache.entityvisible[i])
5219 ent = r_refdef.scene.entities[i];
5220 if (ent->model && ent->model->DrawDepth != NULL)
5221 ent->model->DrawDepth(ent);
5225 static void R_DrawModelsDebug(void)
5228 entity_render_t *ent;
5230 for (i = 0;i < r_refdef.scene.numentities;i++)
5232 if (!r_refdef.viewcache.entityvisible[i])
5234 ent = r_refdef.scene.entities[i];
5235 if (ent->model && ent->model->DrawDebug != NULL)
5236 ent->model->DrawDebug(ent);
5240 static void R_DrawModelsAddWaterPlanes(void)
5243 entity_render_t *ent;
5245 for (i = 0;i < r_refdef.scene.numentities;i++)
5247 if (!r_refdef.viewcache.entityvisible[i])
5249 ent = r_refdef.scene.entities[i];
5250 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5251 ent->model->DrawAddWaterPlanes(ent);
5255 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}};
5257 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5259 if (r_hdr_irisadaptation.integer)
5264 vec3_t diffusenormal;
5266 vec_t brightness = 0.0f;
5271 VectorCopy(r_refdef.view.forward, forward);
5272 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5274 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5275 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5276 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5277 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5278 d = DotProduct(forward, diffusenormal);
5279 brightness += VectorLength(ambient);
5281 brightness += d * VectorLength(diffuse);
5283 brightness *= 1.0f / c;
5284 brightness += 0.00001f; // make sure it's never zero
5285 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5286 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5287 current = r_hdr_irisadaptation_value.value;
5289 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5290 else if (current > goal)
5291 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5292 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5293 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5295 else if (r_hdr_irisadaptation_value.value != 1.0f)
5296 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5299 static void R_View_SetFrustum(const int *scissor)
5302 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5303 vec3_t forward, left, up, origin, v;
5307 // flipped x coordinates (because x points left here)
5308 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5309 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5311 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5312 switch(vid.renderpath)
5314 case RENDERPATH_D3D9:
5315 case RENDERPATH_D3D10:
5316 case RENDERPATH_D3D11:
5317 // non-flipped y coordinates
5318 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5319 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5321 case RENDERPATH_SOFT:
5322 case RENDERPATH_GL11:
5323 case RENDERPATH_GL13:
5324 case RENDERPATH_GL20:
5325 case RENDERPATH_GLES1:
5326 case RENDERPATH_GLES2:
5327 // non-flipped y coordinates
5328 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5329 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5334 // we can't trust r_refdef.view.forward and friends in reflected scenes
5335 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5338 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5339 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5340 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5341 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5342 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5343 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5344 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5345 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5346 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5347 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5348 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5349 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5353 zNear = r_refdef.nearclip;
5354 nudge = 1.0 - 1.0 / (1<<23);
5355 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5356 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5357 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5358 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5359 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5360 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5361 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5362 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5368 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5369 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5370 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5371 r_refdef.view.frustum[0].dist = m[15] - m[12];
5373 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5374 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5375 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5376 r_refdef.view.frustum[1].dist = m[15] + m[12];
5378 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5379 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5380 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5381 r_refdef.view.frustum[2].dist = m[15] - m[13];
5383 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5384 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5385 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5386 r_refdef.view.frustum[3].dist = m[15] + m[13];
5388 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5389 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5390 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5391 r_refdef.view.frustum[4].dist = m[15] - m[14];
5393 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5394 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5395 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5396 r_refdef.view.frustum[5].dist = m[15] + m[14];
5399 if (r_refdef.view.useperspective)
5401 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5402 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]);
5403 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]);
5404 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]);
5405 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]);
5407 // then the normals from the corners relative to origin
5408 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5409 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5410 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5411 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5413 // in a NORMAL view, forward cross left == up
5414 // in a REFLECTED view, forward cross left == down
5415 // so our cross products above need to be adjusted for a left handed coordinate system
5416 CrossProduct(forward, left, v);
5417 if(DotProduct(v, up) < 0)
5419 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5420 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5421 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5422 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5425 // Leaving those out was a mistake, those were in the old code, and they
5426 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5427 // I couldn't reproduce it after adding those normalizations. --blub
5428 VectorNormalize(r_refdef.view.frustum[0].normal);
5429 VectorNormalize(r_refdef.view.frustum[1].normal);
5430 VectorNormalize(r_refdef.view.frustum[2].normal);
5431 VectorNormalize(r_refdef.view.frustum[3].normal);
5433 // make the corners absolute
5434 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5435 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5436 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5437 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5440 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5442 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5443 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5444 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5445 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5446 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5450 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5451 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5452 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5453 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5454 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5455 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5456 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5457 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5458 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5459 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5461 r_refdef.view.numfrustumplanes = 5;
5463 if (r_refdef.view.useclipplane)
5465 r_refdef.view.numfrustumplanes = 6;
5466 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5469 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5470 PlaneClassify(r_refdef.view.frustum + i);
5472 // LordHavoc: note to all quake engine coders, Quake had a special case
5473 // for 90 degrees which assumed a square view (wrong), so I removed it,
5474 // Quake2 has it disabled as well.
5476 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5477 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5478 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5479 //PlaneClassify(&frustum[0]);
5481 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5482 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5483 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5484 //PlaneClassify(&frustum[1]);
5486 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5487 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5488 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5489 //PlaneClassify(&frustum[2]);
5491 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5492 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5493 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5494 //PlaneClassify(&frustum[3]);
5497 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5498 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5499 //PlaneClassify(&frustum[4]);
5502 static void R_View_UpdateWithScissor(const int *myscissor)
5504 R_Main_ResizeViewCache();
5505 R_View_SetFrustum(myscissor);
5506 R_View_WorldVisibility(r_refdef.view.useclipplane);
5507 R_View_UpdateEntityVisible();
5510 static void R_View_Update(void)
5512 R_Main_ResizeViewCache();
5513 R_View_SetFrustum(NULL);
5514 R_View_WorldVisibility(r_refdef.view.useclipplane);
5515 R_View_UpdateEntityVisible();
5518 float viewscalefpsadjusted = 1.0f;
5520 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5522 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5523 scale = bound(0.03125f, scale, 1.0f);
5524 *outwidth = (int)ceil(width * scale);
5525 *outheight = (int)ceil(height * scale);
5528 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5530 const float *customclipplane = NULL;
5532 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5533 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5535 // LordHavoc: couldn't figure out how to make this approach the
5536 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5537 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5538 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5539 dist = r_refdef.view.clipplane.dist;
5540 plane[0] = r_refdef.view.clipplane.normal[0];
5541 plane[1] = r_refdef.view.clipplane.normal[1];
5542 plane[2] = r_refdef.view.clipplane.normal[2];
5544 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5547 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5548 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5550 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5551 if (!r_refdef.view.useperspective)
5552 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);
5553 else if (vid.stencil && r_useinfinitefarclip.integer)
5554 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);
5556 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);
5557 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5558 R_SetViewport(&r_refdef.view.viewport);
5559 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5561 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5562 float screenplane[4];
5563 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5564 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5565 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5566 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5567 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5571 void R_EntityMatrix(const matrix4x4_t *matrix)
5573 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5575 gl_modelmatrixchanged = false;
5576 gl_modelmatrix = *matrix;
5577 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5578 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5579 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5580 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5582 switch(vid.renderpath)
5584 case RENDERPATH_D3D9:
5586 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5587 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5590 case RENDERPATH_D3D10:
5591 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5593 case RENDERPATH_D3D11:
5594 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5596 case RENDERPATH_GL11:
5597 case RENDERPATH_GL13:
5598 case RENDERPATH_GLES1:
5600 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5603 case RENDERPATH_SOFT:
5604 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5605 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5607 case RENDERPATH_GL20:
5608 case RENDERPATH_GLES2:
5609 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5610 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5616 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5618 r_viewport_t viewport;
5622 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5623 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);
5624 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5625 R_SetViewport(&viewport);
5626 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5627 GL_Color(1, 1, 1, 1);
5628 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5629 GL_BlendFunc(GL_ONE, GL_ZERO);
5630 GL_ScissorTest(false);
5631 GL_DepthMask(false);
5632 GL_DepthRange(0, 1);
5633 GL_DepthTest(false);
5634 GL_DepthFunc(GL_LEQUAL);
5635 R_EntityMatrix(&identitymatrix);
5636 R_Mesh_ResetTextureState();
5637 GL_PolygonOffset(0, 0);
5638 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5639 switch(vid.renderpath)
5641 case RENDERPATH_GL11:
5642 case RENDERPATH_GL13:
5643 case RENDERPATH_GL20:
5644 case RENDERPATH_GLES1:
5645 case RENDERPATH_GLES2:
5646 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5648 case RENDERPATH_D3D9:
5649 case RENDERPATH_D3D10:
5650 case RENDERPATH_D3D11:
5651 case RENDERPATH_SOFT:
5654 GL_CullFace(GL_NONE);
5659 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5663 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5666 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5670 R_SetupView(true, fbo, depthtexture, colortexture);
5671 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5672 GL_Color(1, 1, 1, 1);
5673 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5674 GL_BlendFunc(GL_ONE, GL_ZERO);
5675 GL_ScissorTest(true);
5677 GL_DepthRange(0, 1);
5679 GL_DepthFunc(GL_LEQUAL);
5680 R_EntityMatrix(&identitymatrix);
5681 R_Mesh_ResetTextureState();
5682 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5683 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5684 switch(vid.renderpath)
5686 case RENDERPATH_GL11:
5687 case RENDERPATH_GL13:
5688 case RENDERPATH_GL20:
5689 case RENDERPATH_GLES1:
5690 case RENDERPATH_GLES2:
5691 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5693 case RENDERPATH_D3D9:
5694 case RENDERPATH_D3D10:
5695 case RENDERPATH_D3D11:
5696 case RENDERPATH_SOFT:
5699 GL_CullFace(r_refdef.view.cullface_back);
5704 R_RenderView_UpdateViewVectors
5707 void R_RenderView_UpdateViewVectors(void)
5709 // break apart the view matrix into vectors for various purposes
5710 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5711 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5712 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5713 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5714 // make an inverted copy of the view matrix for tracking sprites
5715 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5718 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5719 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5721 static void R_Water_StartFrame(void)
5724 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5725 r_waterstate_waterplane_t *p;
5726 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;
5728 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5731 switch(vid.renderpath)
5733 case RENDERPATH_GL20:
5734 case RENDERPATH_D3D9:
5735 case RENDERPATH_D3D10:
5736 case RENDERPATH_D3D11:
5737 case RENDERPATH_SOFT:
5738 case RENDERPATH_GLES2:
5740 case RENDERPATH_GL11:
5741 case RENDERPATH_GL13:
5742 case RENDERPATH_GLES1:
5746 // set waterwidth and waterheight to the water resolution that will be
5747 // used (often less than the screen resolution for faster rendering)
5748 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5750 // calculate desired texture sizes
5751 // can't use water if the card does not support the texture size
5752 if (!r_water.integer || r_showsurfaces.integer)
5753 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5754 else if (vid.support.arb_texture_non_power_of_two)
5756 texturewidth = waterwidth;
5757 textureheight = waterheight;
5758 camerawidth = waterwidth;
5759 cameraheight = waterheight;
5763 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5764 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5765 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
5766 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
5769 // allocate textures as needed
5770 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))
5772 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5773 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5775 if (p->texture_refraction)
5776 R_FreeTexture(p->texture_refraction);
5777 p->texture_refraction = NULL;
5778 if (p->fbo_refraction)
5779 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5780 p->fbo_refraction = 0;
5781 if (p->texture_reflection)
5782 R_FreeTexture(p->texture_reflection);
5783 p->texture_reflection = NULL;
5784 if (p->fbo_reflection)
5785 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5786 p->fbo_reflection = 0;
5787 if (p->texture_camera)
5788 R_FreeTexture(p->texture_camera);
5789 p->texture_camera = NULL;
5791 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5794 memset(&r_fb.water, 0, sizeof(r_fb.water));
5795 r_fb.water.texturewidth = texturewidth;
5796 r_fb.water.textureheight = textureheight;
5797 r_fb.water.camerawidth = camerawidth;
5798 r_fb.water.cameraheight = cameraheight;
5801 if (r_fb.water.texturewidth)
5803 int scaledwidth, scaledheight;
5805 r_fb.water.enabled = true;
5807 // water resolution is usually reduced
5808 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5809 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5810 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5812 // set up variables that will be used in shader setup
5813 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5814 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5815 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5816 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5819 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5820 r_fb.water.numwaterplanes = 0;
5823 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5825 int planeindex, bestplaneindex, vertexindex;
5826 vec3_t mins, maxs, normal, center, v, n;
5827 vec_t planescore, bestplanescore;
5829 r_waterstate_waterplane_t *p;
5830 texture_t *t = R_GetCurrentTexture(surface->texture);
5832 rsurface.texture = t;
5833 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5834 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5835 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5837 // average the vertex normals, find the surface bounds (after deformvertexes)
5838 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5839 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5840 VectorCopy(n, normal);
5841 VectorCopy(v, mins);
5842 VectorCopy(v, maxs);
5843 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5845 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5846 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5847 VectorAdd(normal, n, normal);
5848 mins[0] = min(mins[0], v[0]);
5849 mins[1] = min(mins[1], v[1]);
5850 mins[2] = min(mins[2], v[2]);
5851 maxs[0] = max(maxs[0], v[0]);
5852 maxs[1] = max(maxs[1], v[1]);
5853 maxs[2] = max(maxs[2], v[2]);
5855 VectorNormalize(normal);
5856 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5858 VectorCopy(normal, plane.normal);
5859 VectorNormalize(plane.normal);
5860 plane.dist = DotProduct(center, plane.normal);
5861 PlaneClassify(&plane);
5862 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5864 // skip backfaces (except if nocullface is set)
5865 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5867 VectorNegate(plane.normal, plane.normal);
5869 PlaneClassify(&plane);
5873 // find a matching plane if there is one
5874 bestplaneindex = -1;
5875 bestplanescore = 1048576.0f;
5876 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5878 if(p->camera_entity == t->camera_entity)
5880 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5881 if (bestplaneindex < 0 || bestplanescore > planescore)
5883 bestplaneindex = planeindex;
5884 bestplanescore = planescore;
5888 planeindex = bestplaneindex;
5890 // if this surface does not fit any known plane rendered this frame, add one
5891 if (planeindex < 0 || bestplanescore > 0.001f)
5893 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5895 // store the new plane
5896 planeindex = r_fb.water.numwaterplanes++;
5897 p = r_fb.water.waterplanes + planeindex;
5899 // clear materialflags and pvs
5900 p->materialflags = 0;
5901 p->pvsvalid = false;
5902 p->camera_entity = t->camera_entity;
5903 VectorCopy(mins, p->mins);
5904 VectorCopy(maxs, p->maxs);
5908 // We're totally screwed.
5914 // merge mins/maxs when we're adding this surface to the plane
5915 p = r_fb.water.waterplanes + planeindex;
5916 p->mins[0] = min(p->mins[0], mins[0]);
5917 p->mins[1] = min(p->mins[1], mins[1]);
5918 p->mins[2] = min(p->mins[2], mins[2]);
5919 p->maxs[0] = max(p->maxs[0], maxs[0]);
5920 p->maxs[1] = max(p->maxs[1], maxs[1]);
5921 p->maxs[2] = max(p->maxs[2], maxs[2]);
5923 // merge this surface's materialflags into the waterplane
5924 p->materialflags |= t->currentmaterialflags;
5925 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5927 // merge this surface's PVS into the waterplane
5928 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5929 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5931 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5937 extern cvar_t r_drawparticles;
5938 extern cvar_t r_drawdecals;
5940 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5943 r_refdef_view_t originalview;
5944 r_refdef_view_t myview;
5945 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;
5946 r_waterstate_waterplane_t *p;
5948 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;
5951 originalview = r_refdef.view;
5953 // lowquality hack, temporarily shut down some cvars and restore afterwards
5954 qualityreduction = r_water_lowquality.integer;
5955 if (qualityreduction > 0)
5957 if (qualityreduction >= 1)
5959 old_r_shadows = r_shadows.integer;
5960 old_r_worldrtlight = r_shadow_realtime_world.integer;
5961 old_r_dlight = r_shadow_realtime_dlight.integer;
5962 Cvar_SetValueQuick(&r_shadows, 0);
5963 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5964 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5966 if (qualityreduction >= 2)
5968 old_r_dynamic = r_dynamic.integer;
5969 old_r_particles = r_drawparticles.integer;
5970 old_r_decals = r_drawdecals.integer;
5971 Cvar_SetValueQuick(&r_dynamic, 0);
5972 Cvar_SetValueQuick(&r_drawparticles, 0);
5973 Cvar_SetValueQuick(&r_drawdecals, 0);
5977 // make sure enough textures are allocated
5978 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5980 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
5982 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5984 if (!p->texture_refraction)
5985 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);
5986 if (!p->texture_refraction)
5990 if (r_fb.water.depthtexture == NULL)
5991 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5992 if (p->fbo_refraction == 0)
5993 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5996 else if (p->materialflags & MATERIALFLAG_CAMERA)
5998 if (!p->texture_camera)
5999 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);
6000 if (!p->texture_camera)
6004 if (r_fb.water.depthtexture == NULL)
6005 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6006 if (p->fbo_camera == 0)
6007 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6011 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6013 if (!p->texture_reflection)
6014 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);
6015 if (!p->texture_reflection)
6019 if (r_fb.water.depthtexture == NULL)
6020 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6021 if (p->fbo_reflection == 0)
6022 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6028 r_refdef.view = originalview;
6029 r_refdef.view.showdebug = false;
6030 r_refdef.view.width = r_fb.water.waterwidth;
6031 r_refdef.view.height = r_fb.water.waterheight;
6032 r_refdef.view.useclipplane = true;
6033 myview = r_refdef.view;
6034 r_fb.water.renderingscene = true;
6035 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6037 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6039 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6041 r_refdef.view = myview;
6042 if(r_water_scissormode.integer)
6044 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6045 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6046 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6049 // render reflected scene and copy into texture
6050 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6051 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6052 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6053 r_refdef.view.clipplane = p->plane;
6054 // reverse the cullface settings for this render
6055 r_refdef.view.cullface_front = GL_FRONT;
6056 r_refdef.view.cullface_back = GL_BACK;
6057 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6059 r_refdef.view.usecustompvs = true;
6061 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6063 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6066 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6067 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6068 R_ClearScreen(r_refdef.fogenabled);
6069 if(r_water_scissormode.integer & 2)
6070 R_View_UpdateWithScissor(myscissor);
6073 R_AnimCache_CacheVisibleEntities();
6074 if(r_water_scissormode.integer & 1)
6075 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6076 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6078 if (!p->fbo_reflection)
6079 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);
6080 r_fb.water.hideplayer = false;
6083 // render the normal view scene and copy into texture
6084 // (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)
6085 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6087 r_refdef.view = myview;
6088 if(r_water_scissormode.integer)
6090 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6091 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6092 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6095 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6097 r_refdef.view.clipplane = p->plane;
6098 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6099 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6101 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6103 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6104 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6105 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6106 R_RenderView_UpdateViewVectors();
6107 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6109 r_refdef.view.usecustompvs = true;
6110 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);
6114 PlaneClassify(&r_refdef.view.clipplane);
6116 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6117 R_ClearScreen(r_refdef.fogenabled);
6118 if(r_water_scissormode.integer & 2)
6119 R_View_UpdateWithScissor(myscissor);
6122 R_AnimCache_CacheVisibleEntities();
6123 if(r_water_scissormode.integer & 1)
6124 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6125 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6127 if (!p->fbo_refraction)
6128 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);
6129 r_fb.water.hideplayer = false;
6131 else if (p->materialflags & MATERIALFLAG_CAMERA)
6133 r_refdef.view = myview;
6135 r_refdef.view.clipplane = p->plane;
6136 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6137 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6139 r_refdef.view.width = r_fb.water.camerawidth;
6140 r_refdef.view.height = r_fb.water.cameraheight;
6141 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6142 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6143 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6144 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6146 if(p->camera_entity)
6148 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6149 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6152 // note: all of the view is used for displaying... so
6153 // there is no use in scissoring
6155 // reverse the cullface settings for this render
6156 r_refdef.view.cullface_front = GL_FRONT;
6157 r_refdef.view.cullface_back = GL_BACK;
6158 // also reverse the view matrix
6159 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
6160 R_RenderView_UpdateViewVectors();
6161 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6163 r_refdef.view.usecustompvs = true;
6164 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);
6167 // camera needs no clipplane
6168 r_refdef.view.useclipplane = false;
6170 PlaneClassify(&r_refdef.view.clipplane);
6172 r_fb.water.hideplayer = false;
6174 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6175 R_ClearScreen(r_refdef.fogenabled);
6177 R_AnimCache_CacheVisibleEntities();
6178 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6181 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);
6182 r_fb.water.hideplayer = false;
6186 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6187 r_fb.water.renderingscene = false;
6188 r_refdef.view = originalview;
6189 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6190 if (!r_fb.water.depthtexture)
6191 R_ClearScreen(r_refdef.fogenabled);
6193 R_AnimCache_CacheVisibleEntities();
6196 r_refdef.view = originalview;
6197 r_fb.water.renderingscene = false;
6198 Cvar_SetValueQuick(&r_water, 0);
6199 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6201 // lowquality hack, restore cvars
6202 if (qualityreduction > 0)
6204 if (qualityreduction >= 1)
6206 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6207 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6208 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6210 if (qualityreduction >= 2)
6212 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6213 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6214 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6219 static void R_Bloom_StartFrame(void)
6222 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6223 int viewwidth, viewheight;
6224 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6225 textype_t textype = TEXTYPE_COLORBUFFER;
6227 switch (vid.renderpath)
6229 case RENDERPATH_GL20:
6230 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6231 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6233 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6234 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6237 case RENDERPATH_GL11:
6238 case RENDERPATH_GL13:
6239 case RENDERPATH_GLES1:
6240 case RENDERPATH_GLES2:
6241 case RENDERPATH_D3D9:
6242 case RENDERPATH_D3D10:
6243 case RENDERPATH_D3D11:
6244 r_fb.usedepthtextures = false;
6246 case RENDERPATH_SOFT:
6247 r_fb.usedepthtextures = true;
6251 if (r_viewscale_fpsscaling.integer)
6253 double actualframetime;
6254 double targetframetime;
6256 actualframetime = r_refdef.lastdrawscreentime;
6257 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6258 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6259 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6260 if (r_viewscale_fpsscaling_stepsize.value > 0)
6261 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6262 viewscalefpsadjusted += adjust;
6263 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6266 viewscalefpsadjusted = 1.0f;
6268 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6270 switch(vid.renderpath)
6272 case RENDERPATH_GL20:
6273 case RENDERPATH_D3D9:
6274 case RENDERPATH_D3D10:
6275 case RENDERPATH_D3D11:
6276 case RENDERPATH_SOFT:
6277 case RENDERPATH_GLES2:
6279 case RENDERPATH_GL11:
6280 case RENDERPATH_GL13:
6281 case RENDERPATH_GLES1:
6285 // set bloomwidth and bloomheight to the bloom resolution that will be
6286 // used (often less than the screen resolution for faster rendering)
6287 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6288 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6289 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6290 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6291 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6293 // calculate desired texture sizes
6294 if (vid.support.arb_texture_non_power_of_two)
6296 screentexturewidth = vid.width;
6297 screentextureheight = vid.height;
6298 bloomtexturewidth = r_fb.bloomwidth;
6299 bloomtextureheight = r_fb.bloomheight;
6303 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6304 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6305 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6306 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6309 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))
6311 Cvar_SetValueQuick(&r_bloom, 0);
6312 Cvar_SetValueQuick(&r_motionblur, 0);
6313 Cvar_SetValueQuick(&r_damageblur, 0);
6316 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6318 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6320 && r_viewscale.value == 1.0f
6321 && !r_viewscale_fpsscaling.integer)
6322 screentexturewidth = screentextureheight = 0;
6323 if (!r_bloom.integer)
6324 bloomtexturewidth = bloomtextureheight = 0;
6326 // allocate textures as needed
6327 if (r_fb.screentexturewidth != screentexturewidth
6328 || r_fb.screentextureheight != screentextureheight
6329 || r_fb.bloomtexturewidth != bloomtexturewidth
6330 || r_fb.bloomtextureheight != bloomtextureheight
6331 || r_fb.textype != textype
6332 || useviewfbo != (r_fb.fbo != 0))
6334 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6336 if (r_fb.bloomtexture[i])
6337 R_FreeTexture(r_fb.bloomtexture[i]);
6338 r_fb.bloomtexture[i] = NULL;
6340 if (r_fb.bloomfbo[i])
6341 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6342 r_fb.bloomfbo[i] = 0;
6346 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6349 if (r_fb.colortexture)
6350 R_FreeTexture(r_fb.colortexture);
6351 r_fb.colortexture = NULL;
6353 if (r_fb.depthtexture)
6354 R_FreeTexture(r_fb.depthtexture);
6355 r_fb.depthtexture = NULL;
6357 if (r_fb.ghosttexture)
6358 R_FreeTexture(r_fb.ghosttexture);
6359 r_fb.ghosttexture = NULL;
6361 r_fb.screentexturewidth = screentexturewidth;
6362 r_fb.screentextureheight = screentextureheight;
6363 r_fb.bloomtexturewidth = bloomtexturewidth;
6364 r_fb.bloomtextureheight = bloomtextureheight;
6365 r_fb.textype = textype;
6367 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6369 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6370 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);
6371 r_fb.ghosttexture_valid = false;
6372 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);
6375 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6376 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6377 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6381 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6383 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6385 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);
6387 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6392 // bloom texture is a different resolution
6393 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6394 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6395 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6396 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6397 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6399 // set up a texcoord array for the full resolution screen image
6400 // (we have to keep this around to copy back during final render)
6401 r_fb.screentexcoord2f[0] = 0;
6402 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6403 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6404 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6405 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6406 r_fb.screentexcoord2f[5] = 0;
6407 r_fb.screentexcoord2f[6] = 0;
6408 r_fb.screentexcoord2f[7] = 0;
6412 for (i = 1;i < 8;i += 2)
6414 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6418 // set up a texcoord array for the reduced resolution bloom image
6419 // (which will be additive blended over the screen image)
6420 r_fb.bloomtexcoord2f[0] = 0;
6421 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6422 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6423 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6424 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6425 r_fb.bloomtexcoord2f[5] = 0;
6426 r_fb.bloomtexcoord2f[6] = 0;
6427 r_fb.bloomtexcoord2f[7] = 0;
6429 switch(vid.renderpath)
6431 case RENDERPATH_GL11:
6432 case RENDERPATH_GL13:
6433 case RENDERPATH_GL20:
6434 case RENDERPATH_SOFT:
6435 case RENDERPATH_GLES1:
6436 case RENDERPATH_GLES2:
6438 case RENDERPATH_D3D9:
6439 case RENDERPATH_D3D10:
6440 case RENDERPATH_D3D11:
6441 for (i = 0;i < 4;i++)
6443 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6444 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6445 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6446 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6451 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6454 r_refdef.view.clear = true;
6457 static void R_Bloom_MakeTexture(void)
6460 float xoffset, yoffset, r, brighten;
6462 float colorscale = r_bloom_colorscale.value;
6464 r_refdef.stats[r_stat_bloom]++;
6467 // this copy is unnecessary since it happens in R_BlendView already
6470 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);
6471 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6475 // scale down screen texture to the bloom texture size
6477 r_fb.bloomindex = 0;
6478 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6479 R_SetViewport(&r_fb.bloomviewport);
6480 GL_CullFace(GL_NONE);
6481 GL_DepthTest(false);
6482 GL_BlendFunc(GL_ONE, GL_ZERO);
6483 GL_Color(colorscale, colorscale, colorscale, 1);
6484 // 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...
6485 switch(vid.renderpath)
6487 case RENDERPATH_GL11:
6488 case RENDERPATH_GL13:
6489 case RENDERPATH_GL20:
6490 case RENDERPATH_GLES1:
6491 case RENDERPATH_GLES2:
6492 case RENDERPATH_SOFT:
6493 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6495 case RENDERPATH_D3D9:
6496 case RENDERPATH_D3D10:
6497 case RENDERPATH_D3D11:
6498 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6501 // TODO: do boxfilter scale-down in shader?
6502 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6503 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6504 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6506 // we now have a properly scaled bloom image
6507 if (!r_fb.bloomfbo[r_fb.bloomindex])
6509 // copy it into the bloom texture
6510 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);
6511 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6514 // multiply bloom image by itself as many times as desired
6515 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6517 intex = r_fb.bloomtexture[r_fb.bloomindex];
6518 r_fb.bloomindex ^= 1;
6519 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6521 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6522 if (!r_fb.bloomfbo[r_fb.bloomindex])
6524 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6525 GL_Color(r,r,r,1); // apply fix factor
6530 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6531 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6532 GL_Color(1,1,1,1); // no fix factor supported here
6534 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6535 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6536 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6537 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6539 if (!r_fb.bloomfbo[r_fb.bloomindex])
6541 // copy the darkened image to a texture
6542 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);
6543 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6547 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6548 brighten = r_bloom_brighten.value;
6549 brighten = sqrt(brighten);
6551 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6553 for (dir = 0;dir < 2;dir++)
6555 intex = r_fb.bloomtexture[r_fb.bloomindex];
6556 r_fb.bloomindex ^= 1;
6557 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6558 // blend on at multiple vertical offsets to achieve a vertical blur
6559 // TODO: do offset blends using GLSL
6560 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6561 GL_BlendFunc(GL_ONE, GL_ZERO);
6562 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6563 for (x = -range;x <= range;x++)
6565 if (!dir){xoffset = 0;yoffset = x;}
6566 else {xoffset = x;yoffset = 0;}
6567 xoffset /= (float)r_fb.bloomtexturewidth;
6568 yoffset /= (float)r_fb.bloomtextureheight;
6569 // compute a texcoord array with the specified x and y offset
6570 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6571 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6572 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6573 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6574 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6575 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6576 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6577 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6578 // this r value looks like a 'dot' particle, fading sharply to
6579 // black at the edges
6580 // (probably not realistic but looks good enough)
6581 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6582 //r = brighten/(range*2+1);
6583 r = brighten / (range * 2 + 1);
6585 r *= (1 - x*x/(float)(range*range));
6586 GL_Color(r, r, r, 1);
6587 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6588 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6589 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6590 GL_BlendFunc(GL_ONE, GL_ONE);
6593 if (!r_fb.bloomfbo[r_fb.bloomindex])
6595 // copy the vertically or horizontally blurred bloom view to a texture
6596 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);
6597 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6602 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6604 dpuint64 permutation;
6605 float uservecs[4][4];
6607 R_EntityMatrix(&identitymatrix);
6609 switch (vid.renderpath)
6611 case RENDERPATH_GL20:
6612 case RENDERPATH_D3D9:
6613 case RENDERPATH_D3D10:
6614 case RENDERPATH_D3D11:
6615 case RENDERPATH_SOFT:
6616 case RENDERPATH_GLES2:
6618 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6619 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6620 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6621 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6622 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6624 if (r_fb.colortexture)
6628 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);
6629 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6632 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6634 // declare variables
6635 float blur_factor, blur_mouseaccel, blur_velocity;
6636 static float blur_average;
6637 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6639 // set a goal for the factoring
6640 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6641 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6642 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6643 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6644 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6645 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6647 // from the goal, pick an averaged value between goal and last value
6648 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6649 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6651 // enforce minimum amount of blur
6652 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6654 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6656 // calculate values into a standard alpha
6657 cl.motionbluralpha = 1 - exp(-
6659 (r_motionblur.value * blur_factor / 80)
6661 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6664 max(0.0001, cl.time - cl.oldtime) // fps independent
6667 // randomization for the blur value to combat persistent ghosting
6668 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6669 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6672 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6673 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6675 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6676 GL_Color(1, 1, 1, cl.motionbluralpha);
6677 switch(vid.renderpath)
6679 case RENDERPATH_GL11:
6680 case RENDERPATH_GL13:
6681 case RENDERPATH_GL20:
6682 case RENDERPATH_GLES1:
6683 case RENDERPATH_GLES2:
6684 case RENDERPATH_SOFT:
6685 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6687 case RENDERPATH_D3D9:
6688 case RENDERPATH_D3D10:
6689 case RENDERPATH_D3D11:
6690 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6693 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6694 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6695 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6698 // updates old view angles for next pass
6699 VectorCopy(cl.viewangles, blur_oldangles);
6701 // copy view into the ghost texture
6702 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);
6703 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6704 r_fb.ghosttexture_valid = true;
6709 // no r_fb.colortexture means we're rendering to the real fb
6710 // we may still have to do view tint...
6711 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6713 // apply a color tint to the whole view
6714 R_ResetViewRendering2D(0, NULL, NULL);
6715 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6716 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6717 R_SetupShader_Generic_NoTexture(false, true);
6718 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6719 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6721 break; // no screen processing, no bloom, skip it
6724 if (r_fb.bloomtexture[0])
6726 // make the bloom texture
6727 R_Bloom_MakeTexture();
6730 #if _MSC_VER >= 1400
6731 #define sscanf sscanf_s
6733 memset(uservecs, 0, sizeof(uservecs));
6734 if (r_glsl_postprocess_uservec1_enable.integer)
6735 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6736 if (r_glsl_postprocess_uservec2_enable.integer)
6737 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6738 if (r_glsl_postprocess_uservec3_enable.integer)
6739 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6740 if (r_glsl_postprocess_uservec4_enable.integer)
6741 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6743 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6744 GL_Color(1, 1, 1, 1);
6745 GL_BlendFunc(GL_ONE, GL_ZERO);
6747 switch(vid.renderpath)
6749 case RENDERPATH_GL20:
6750 case RENDERPATH_GLES2:
6751 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6752 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6753 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
6754 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
6755 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6756 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]);
6757 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6758 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]);
6759 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]);
6760 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]);
6761 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]);
6762 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6763 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6764 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);
6766 case RENDERPATH_D3D9:
6768 // 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...
6769 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6770 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6771 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6772 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6773 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6774 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6775 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6776 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6777 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6778 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6779 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6780 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6781 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6782 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6785 case RENDERPATH_D3D10:
6786 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6788 case RENDERPATH_D3D11:
6789 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6791 case RENDERPATH_SOFT:
6792 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6793 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6794 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
6795 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
6796 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6797 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6798 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6799 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6800 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6801 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6802 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6804 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6805 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6810 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6811 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6813 case RENDERPATH_GL11:
6814 case RENDERPATH_GL13:
6815 case RENDERPATH_GLES1:
6816 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6818 // apply a color tint to the whole view
6819 R_ResetViewRendering2D(0, NULL, NULL);
6820 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6821 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6822 R_SetupShader_Generic_NoTexture(false, true);
6823 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6824 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6830 matrix4x4_t r_waterscrollmatrix;
6832 void R_UpdateFog(void)
6835 if (gamemode == GAME_NEHAHRA)
6837 if (gl_fogenable.integer)
6839 r_refdef.oldgl_fogenable = true;
6840 r_refdef.fog_density = gl_fogdensity.value;
6841 r_refdef.fog_red = gl_fogred.value;
6842 r_refdef.fog_green = gl_foggreen.value;
6843 r_refdef.fog_blue = gl_fogblue.value;
6844 r_refdef.fog_alpha = 1;
6845 r_refdef.fog_start = 0;
6846 r_refdef.fog_end = gl_skyclip.value;
6847 r_refdef.fog_height = 1<<30;
6848 r_refdef.fog_fadedepth = 128;
6850 else if (r_refdef.oldgl_fogenable)
6852 r_refdef.oldgl_fogenable = false;
6853 r_refdef.fog_density = 0;
6854 r_refdef.fog_red = 0;
6855 r_refdef.fog_green = 0;
6856 r_refdef.fog_blue = 0;
6857 r_refdef.fog_alpha = 0;
6858 r_refdef.fog_start = 0;
6859 r_refdef.fog_end = 0;
6860 r_refdef.fog_height = 1<<30;
6861 r_refdef.fog_fadedepth = 128;
6866 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6867 r_refdef.fog_start = max(0, r_refdef.fog_start);
6868 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6870 if (r_refdef.fog_density && r_drawfog.integer)
6872 r_refdef.fogenabled = true;
6873 // this is the point where the fog reaches 0.9986 alpha, which we
6874 // consider a good enough cutoff point for the texture
6875 // (0.9986 * 256 == 255.6)
6876 if (r_fog_exp2.integer)
6877 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6879 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6880 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6881 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6882 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6883 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6884 R_BuildFogHeightTexture();
6885 // fog color was already set
6886 // update the fog texture
6887 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)
6888 R_BuildFogTexture();
6889 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6890 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6893 r_refdef.fogenabled = false;
6896 if (r_refdef.fog_density)
6898 r_refdef.fogcolor[0] = r_refdef.fog_red;
6899 r_refdef.fogcolor[1] = r_refdef.fog_green;
6900 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6902 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6903 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6904 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6905 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6909 VectorCopy(r_refdef.fogcolor, fogvec);
6910 // color.rgb *= ContrastBoost * SceneBrightness;
6911 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6912 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6913 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6914 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6919 void R_UpdateVariables(void)
6923 r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6925 r_refdef.farclip = r_farclip_base.value;
6926 if (r_refdef.scene.worldmodel)
6927 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6928 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6930 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6931 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6932 r_refdef.polygonfactor = 0;
6933 r_refdef.polygonoffset = 0;
6934 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6935 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6937 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6938 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6939 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6940 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6941 r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6942 if (FAKELIGHT_ENABLED)
6944 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6946 else if (r_refdef.scene.worldmodel)
6948 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6950 if (r_showsurfaces.integer)
6952 r_refdef.scene.rtworld = false;
6953 r_refdef.scene.rtworldshadows = false;
6954 r_refdef.scene.rtdlight = false;
6955 r_refdef.scene.rtdlightshadows = false;
6956 r_refdef.scene.lightmapintensity = 0;
6959 r_gpuskeletal = false;
6960 switch(vid.renderpath)
6962 case RENDERPATH_GL20:
6963 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6964 case RENDERPATH_D3D9:
6965 case RENDERPATH_D3D10:
6966 case RENDERPATH_D3D11:
6967 case RENDERPATH_SOFT:
6968 case RENDERPATH_GLES2:
6969 if(v_glslgamma.integer && !vid_gammatables_trivial)
6971 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6973 // build GLSL gamma texture
6974 #define RAMPWIDTH 256
6975 unsigned short ramp[RAMPWIDTH * 3];
6976 unsigned char rampbgr[RAMPWIDTH][4];
6979 r_texture_gammaramps_serial = vid_gammatables_serial;
6981 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6982 for(i = 0; i < RAMPWIDTH; ++i)
6984 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6985 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6986 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6989 if (r_texture_gammaramps)
6991 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6995 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7001 // remove GLSL gamma texture
7004 case RENDERPATH_GL11:
7005 case RENDERPATH_GL13:
7006 case RENDERPATH_GLES1:
7011 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7012 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7018 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7019 if( scenetype != r_currentscenetype ) {
7020 // store the old scenetype
7021 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7022 r_currentscenetype = scenetype;
7023 // move in the new scene
7024 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7033 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7035 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7036 if( scenetype == r_currentscenetype ) {
7037 return &r_refdef.scene;
7039 return &r_scenes_store[ scenetype ];
7043 static int R_SortEntities_Compare(const void *ap, const void *bp)
7045 const entity_render_t *a = *(const entity_render_t **)ap;
7046 const entity_render_t *b = *(const entity_render_t **)bp;
7049 if(a->model < b->model)
7051 if(a->model > b->model)
7055 // TODO possibly calculate the REAL skinnum here first using
7057 if(a->skinnum < b->skinnum)
7059 if(a->skinnum > b->skinnum)
7062 // everything we compared is equal
7065 static void R_SortEntities(void)
7067 // below or equal 2 ents, sorting never gains anything
7068 if(r_refdef.scene.numentities <= 2)
7071 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7079 int dpsoftrast_test;
7080 extern cvar_t r_shadow_bouncegrid;
7081 void R_RenderView(void)
7083 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7085 rtexture_t *depthtexture;
7086 rtexture_t *colortexture;
7088 dpsoftrast_test = r_test.integer;
7090 if (r_timereport_active)
7091 R_TimeReport("start");
7092 r_textureframe++; // used only by R_GetCurrentTexture
7093 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
7095 if(R_CompileShader_CheckStaticParms())
7098 if (!r_drawentities.integer)
7099 r_refdef.scene.numentities = 0;
7100 else if (r_sortentities.integer)
7103 R_AnimCache_ClearCache();
7105 /* adjust for stereo display */
7106 if(R_Stereo_Active())
7108 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);
7109 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7112 if (r_refdef.view.isoverlay)
7114 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7115 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7116 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7117 R_TimeReport("depthclear");
7119 r_refdef.view.showdebug = false;
7121 r_fb.water.enabled = false;
7122 r_fb.water.numwaterplanes = 0;
7124 R_RenderScene(0, NULL, NULL);
7126 r_refdef.view.matrix = originalmatrix;
7132 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7134 r_refdef.view.matrix = originalmatrix;
7138 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7140 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7141 // in sRGB fallback, behave similar to true sRGB: convert this
7142 // value from linear to sRGB
7143 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7145 R_RenderView_UpdateViewVectors();
7147 R_Shadow_UpdateWorldLightSelection();
7149 R_Bloom_StartFrame();
7151 // apply bloom brightness offset
7152 if(r_fb.bloomtexture[0])
7153 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7155 R_Water_StartFrame();
7157 // now we probably have an fbo to render into
7159 depthtexture = r_fb.depthtexture;
7160 colortexture = r_fb.colortexture;
7163 if (r_timereport_active)
7164 R_TimeReport("viewsetup");
7166 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7168 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7170 R_ClearScreen(r_refdef.fogenabled);
7171 if (r_timereport_active)
7172 R_TimeReport("viewclear");
7174 r_refdef.view.clear = true;
7176 r_refdef.view.showdebug = true;
7179 if (r_timereport_active)
7180 R_TimeReport("visibility");
7182 R_AnimCache_CacheVisibleEntities();
7183 if (r_timereport_active)
7184 R_TimeReport("animcache");
7186 R_Shadow_UpdateBounceGridTexture();
7187 if (r_timereport_active && r_shadow_bouncegrid.integer)
7188 R_TimeReport("bouncegrid");
7190 r_fb.water.numwaterplanes = 0;
7191 if (r_fb.water.enabled)
7192 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7194 R_RenderScene(fbo, depthtexture, colortexture);
7195 r_fb.water.numwaterplanes = 0;
7197 R_BlendView(fbo, depthtexture, colortexture);
7198 if (r_timereport_active)
7199 R_TimeReport("blendview");
7201 GL_Scissor(0, 0, vid.width, vid.height);
7202 GL_ScissorTest(false);
7204 r_refdef.view.matrix = originalmatrix;
7209 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7211 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7213 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7214 if (r_timereport_active)
7215 R_TimeReport("waterworld");
7218 // don't let sound skip if going slow
7219 if (r_refdef.scene.extraupdate)
7222 R_DrawModelsAddWaterPlanes();
7223 if (r_timereport_active)
7224 R_TimeReport("watermodels");
7226 if (r_fb.water.numwaterplanes)
7228 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7229 if (r_timereport_active)
7230 R_TimeReport("waterscenes");
7234 extern cvar_t cl_locs_show;
7235 static void R_DrawLocs(void);
7236 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7237 static void R_DrawModelDecals(void);
7238 extern cvar_t cl_decals_newsystem;
7239 extern qboolean r_shadow_usingdeferredprepass;
7240 extern int r_shadow_shadowmapatlas_modelshadows_size;
7241 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7243 qboolean shadowmapping = false;
7245 if (r_timereport_active)
7246 R_TimeReport("beginscene");
7248 r_refdef.stats[r_stat_renders]++;
7252 // don't let sound skip if going slow
7253 if (r_refdef.scene.extraupdate)
7256 R_MeshQueue_BeginScene();
7260 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);
7262 if (r_timereport_active)
7263 R_TimeReport("skystartframe");
7265 if (cl.csqc_vidvars.drawworld)
7267 // don't let sound skip if going slow
7268 if (r_refdef.scene.extraupdate)
7271 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7273 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7274 if (r_timereport_active)
7275 R_TimeReport("worldsky");
7278 if (R_DrawBrushModelsSky() && r_timereport_active)
7279 R_TimeReport("bmodelsky");
7281 if (skyrendermasked && skyrenderlater)
7283 // we have to force off the water clipping plane while rendering sky
7284 R_SetupView(false, fbo, depthtexture, colortexture);
7286 R_SetupView(true, fbo, depthtexture, colortexture);
7287 if (r_timereport_active)
7288 R_TimeReport("sky");
7292 R_Shadow_PrepareModelShadows();
7293 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7294 if (r_timereport_active)
7295 R_TimeReport("preparelights");
7297 // render all the shadowmaps that will be used for this view
7298 shadowmapping = R_Shadow_ShadowMappingEnabled();
7299 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7301 R_Shadow_DrawShadowMaps();
7302 if (r_timereport_active)
7303 R_TimeReport("shadowmaps");
7306 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7307 if (r_shadow_usingdeferredprepass)
7308 R_Shadow_DrawPrepass();
7310 // now we begin the forward pass of the view render
7311 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7313 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7314 if (r_timereport_active)
7315 R_TimeReport("worlddepth");
7317 if (r_depthfirst.integer >= 2)
7319 R_DrawModelsDepth();
7320 if (r_timereport_active)
7321 R_TimeReport("modeldepth");
7324 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7326 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7327 if (r_timereport_active)
7328 R_TimeReport("world");
7331 // don't let sound skip if going slow
7332 if (r_refdef.scene.extraupdate)
7336 if (r_timereport_active)
7337 R_TimeReport("models");
7339 // don't let sound skip if going slow
7340 if (r_refdef.scene.extraupdate)
7343 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7345 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7346 R_Shadow_DrawModelShadows();
7347 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7348 // don't let sound skip if going slow
7349 if (r_refdef.scene.extraupdate)
7353 if (!r_shadow_usingdeferredprepass)
7355 R_Shadow_DrawLights();
7356 if (r_timereport_active)
7357 R_TimeReport("rtlights");
7360 // don't let sound skip if going slow
7361 if (r_refdef.scene.extraupdate)
7364 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7366 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7367 R_Shadow_DrawModelShadows();
7368 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7369 // don't let sound skip if going slow
7370 if (r_refdef.scene.extraupdate)
7374 if (cl.csqc_vidvars.drawworld)
7376 if (cl_decals_newsystem.integer)
7378 R_DrawModelDecals();
7379 if (r_timereport_active)
7380 R_TimeReport("modeldecals");
7385 if (r_timereport_active)
7386 R_TimeReport("decals");
7390 if (r_timereport_active)
7391 R_TimeReport("particles");
7394 if (r_timereport_active)
7395 R_TimeReport("explosions");
7399 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7401 if (r_refdef.view.showdebug)
7403 if (cl_locs_show.integer)
7406 if (r_timereport_active)
7407 R_TimeReport("showlocs");
7410 if (r_drawportals.integer)
7413 if (r_timereport_active)
7414 R_TimeReport("portals");
7417 if (r_showbboxes_client.value > 0)
7419 R_DrawEntityBBoxes(CLVM_prog);
7420 if (r_timereport_active)
7421 R_TimeReport("clbboxes");
7423 if (r_showbboxes.value > 0)
7425 R_DrawEntityBBoxes(SVVM_prog);
7426 if (r_timereport_active)
7427 R_TimeReport("svbboxes");
7431 if (r_transparent.integer)
7433 R_MeshQueue_RenderTransparent();
7434 if (r_timereport_active)
7435 R_TimeReport("drawtrans");
7438 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))
7440 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7441 if (r_timereport_active)
7442 R_TimeReport("worlddebug");
7443 R_DrawModelsDebug();
7444 if (r_timereport_active)
7445 R_TimeReport("modeldebug");
7448 if (cl.csqc_vidvars.drawworld)
7450 R_Shadow_DrawCoronas();
7451 if (r_timereport_active)
7452 R_TimeReport("coronas");
7457 GL_DepthTest(false);
7458 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7459 GL_Color(1, 1, 1, 1);
7460 qglBegin(GL_POLYGON);
7461 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7462 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7463 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7464 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7466 qglBegin(GL_POLYGON);
7467 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]);
7468 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]);
7469 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]);
7470 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]);
7472 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7476 // don't let sound skip if going slow
7477 if (r_refdef.scene.extraupdate)
7481 static const unsigned short bboxelements[36] =
7491 #define BBOXEDGES 13
7492 static const float bboxedges[BBOXEDGES][6] =
7495 { 0, 0, 0, 1, 1, 1 },
7497 { 0, 0, 0, 0, 1, 0 },
7498 { 0, 0, 0, 1, 0, 0 },
7499 { 0, 1, 0, 1, 1, 0 },
7500 { 1, 0, 0, 1, 1, 0 },
7502 { 0, 0, 1, 0, 1, 1 },
7503 { 0, 0, 1, 1, 0, 1 },
7504 { 0, 1, 1, 1, 1, 1 },
7505 { 1, 0, 1, 1, 1, 1 },
7507 { 0, 0, 0, 0, 0, 1 },
7508 { 1, 0, 0, 1, 0, 1 },
7509 { 0, 1, 0, 0, 1, 1 },
7510 { 1, 1, 0, 1, 1, 1 },
7513 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7515 int numvertices = BBOXEDGES * 8;
7516 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7517 int numtriangles = BBOXEDGES * 12;
7518 unsigned short elements[BBOXEDGES * 36];
7520 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7522 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7524 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7525 GL_DepthMask(false);
7526 GL_DepthRange(0, 1);
7527 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7529 for (edge = 0; edge < BBOXEDGES; edge++)
7531 for (i = 0; i < 3; i++)
7533 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7534 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7536 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7537 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7538 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7539 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7540 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7541 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7542 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7543 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7544 for (i = 0; i < 36; i++)
7545 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7547 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7548 if (r_refdef.fogenabled)
7550 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7552 f1 = RSurf_FogVertex(v);
7554 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7555 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7556 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7559 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7560 R_Mesh_ResetTextureState();
7561 R_SetupShader_Generic_NoTexture(false, false);
7562 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7565 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7567 // hacky overloading of the parameters
7568 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7571 prvm_edict_t *edict;
7573 GL_CullFace(GL_NONE);
7574 R_SetupShader_Generic_NoTexture(false, false);
7576 for (i = 0;i < numsurfaces;i++)
7578 edict = PRVM_EDICT_NUM(surfacelist[i]);
7579 switch ((int)PRVM_serveredictfloat(edict, solid))
7581 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7582 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7583 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7584 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7585 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7586 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7587 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7589 if (prog == CLVM_prog)
7590 color[3] *= r_showbboxes_client.value;
7592 color[3] *= r_showbboxes.value;
7593 color[3] = bound(0, color[3], 1);
7594 GL_DepthTest(!r_showdisabledepthtest.integer);
7595 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7599 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7602 prvm_edict_t *edict;
7608 for (i = 0; i < prog->num_edicts; i++)
7610 edict = PRVM_EDICT_NUM(i);
7611 if (edict->priv.server->free)
7613 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7614 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7616 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7618 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7619 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7623 static const int nomodelelement3i[24] =
7635 static const unsigned short nomodelelement3s[24] =
7647 static const float nomodelvertex3f[6*3] =
7657 static const float nomodelcolor4f[6*4] =
7659 0.0f, 0.0f, 0.5f, 1.0f,
7660 0.0f, 0.0f, 0.5f, 1.0f,
7661 0.0f, 0.5f, 0.0f, 1.0f,
7662 0.0f, 0.5f, 0.0f, 1.0f,
7663 0.5f, 0.0f, 0.0f, 1.0f,
7664 0.5f, 0.0f, 0.0f, 1.0f
7667 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7673 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);
7675 // this is only called once per entity so numsurfaces is always 1, and
7676 // surfacelist is always {0}, so this code does not handle batches
7678 if (rsurface.ent_flags & RENDER_ADDITIVE)
7680 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7681 GL_DepthMask(false);
7683 else if (ent->alpha < 1)
7685 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7686 GL_DepthMask(false);
7690 GL_BlendFunc(GL_ONE, GL_ZERO);
7693 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7694 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7695 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7696 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7697 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7698 for (i = 0, c = color4f;i < 6;i++, c += 4)
7700 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7701 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7702 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7705 if (r_refdef.fogenabled)
7707 for (i = 0, c = color4f;i < 6;i++, c += 4)
7709 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7711 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7712 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7713 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7716 // R_Mesh_ResetTextureState();
7717 R_SetupShader_Generic_NoTexture(false, false);
7718 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7719 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7722 void R_DrawNoModel(entity_render_t *ent)
7725 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7726 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7727 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7729 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7732 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7734 vec3_t right1, right2, diff, normal;
7736 VectorSubtract (org2, org1, normal);
7738 // calculate 'right' vector for start
7739 VectorSubtract (r_refdef.view.origin, org1, diff);
7740 CrossProduct (normal, diff, right1);
7741 VectorNormalize (right1);
7743 // calculate 'right' vector for end
7744 VectorSubtract (r_refdef.view.origin, org2, diff);
7745 CrossProduct (normal, diff, right2);
7746 VectorNormalize (right2);
7748 vert[ 0] = org1[0] + width * right1[0];
7749 vert[ 1] = org1[1] + width * right1[1];
7750 vert[ 2] = org1[2] + width * right1[2];
7751 vert[ 3] = org1[0] - width * right1[0];
7752 vert[ 4] = org1[1] - width * right1[1];
7753 vert[ 5] = org1[2] - width * right1[2];
7754 vert[ 6] = org2[0] - width * right2[0];
7755 vert[ 7] = org2[1] - width * right2[1];
7756 vert[ 8] = org2[2] - width * right2[2];
7757 vert[ 9] = org2[0] + width * right2[0];
7758 vert[10] = org2[1] + width * right2[1];
7759 vert[11] = org2[2] + width * right2[2];
7762 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)
7764 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7765 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7766 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7767 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7768 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7769 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7770 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7771 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7772 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7773 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7774 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7775 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7778 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7783 VectorSet(v, x, y, z);
7784 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7785 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7787 if (i == mesh->numvertices)
7789 if (mesh->numvertices < mesh->maxvertices)
7791 VectorCopy(v, vertex3f);
7792 mesh->numvertices++;
7794 return mesh->numvertices;
7800 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7804 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7805 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7806 e = mesh->element3i + mesh->numtriangles * 3;
7807 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7809 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7810 if (mesh->numtriangles < mesh->maxtriangles)
7815 mesh->numtriangles++;
7817 element[1] = element[2];
7821 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7825 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7826 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7827 e = mesh->element3i + mesh->numtriangles * 3;
7828 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7830 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7831 if (mesh->numtriangles < mesh->maxtriangles)
7836 mesh->numtriangles++;
7838 element[1] = element[2];
7842 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7843 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7845 int planenum, planenum2;
7848 mplane_t *plane, *plane2;
7850 double temppoints[2][256*3];
7851 // figure out how large a bounding box we need to properly compute this brush
7853 for (w = 0;w < numplanes;w++)
7854 maxdist = max(maxdist, fabs(planes[w].dist));
7855 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7856 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7857 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7861 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7862 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7864 if (planenum2 == planenum)
7866 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);
7869 if (tempnumpoints < 3)
7871 // generate elements forming a triangle fan for this polygon
7872 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7876 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)
7878 texturelayer_t *layer;
7879 layer = t->currentlayers + t->currentnumlayers++;
7881 layer->depthmask = depthmask;
7882 layer->blendfunc1 = blendfunc1;
7883 layer->blendfunc2 = blendfunc2;
7884 layer->texture = texture;
7885 layer->texmatrix = *matrix;
7886 layer->color[0] = r;
7887 layer->color[1] = g;
7888 layer->color[2] = b;
7889 layer->color[3] = a;
7892 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7894 if(parms[0] == 0 && parms[1] == 0)
7896 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7897 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7902 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7905 index = parms[2] + rsurface.shadertime * parms[3];
7906 index -= floor(index);
7907 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7910 case Q3WAVEFUNC_NONE:
7911 case Q3WAVEFUNC_NOISE:
7912 case Q3WAVEFUNC_COUNT:
7915 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7916 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7917 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7918 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7919 case Q3WAVEFUNC_TRIANGLE:
7921 f = index - floor(index);
7934 f = parms[0] + parms[1] * f;
7935 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7936 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7940 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7947 matrix4x4_t matrix, temp;
7948 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7949 // it's better to have one huge fixup every 9 hours than gradual
7950 // degradation over time which looks consistently bad after many hours.
7952 // tcmod scroll in particular suffers from this degradation which can't be
7953 // effectively worked around even with floor() tricks because we don't
7954 // know if tcmod scroll is the last tcmod being applied, and for clampmap
7955 // a workaround involving floor() would be incorrect anyway...
7956 shadertime = rsurface.shadertime;
7957 if (shadertime >= 32768.0f)
7958 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7959 switch(tcmod->tcmod)
7963 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7964 matrix = r_waterscrollmatrix;
7966 matrix = identitymatrix;
7968 case Q3TCMOD_ENTITYTRANSLATE:
7969 // this is used in Q3 to allow the gamecode to control texcoord
7970 // scrolling on the entity, which is not supported in darkplaces yet.
7971 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7973 case Q3TCMOD_ROTATE:
7974 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7975 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7976 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7979 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7981 case Q3TCMOD_SCROLL:
7982 // this particular tcmod is a "bug for bug" compatible one with regards to
7983 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7984 // specifically did the wrapping and so we must mimic that...
7985 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7986 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7987 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7989 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7990 w = (int) tcmod->parms[0];
7991 h = (int) tcmod->parms[1];
7992 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7994 idx = (int) floor(f * w * h);
7995 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7997 case Q3TCMOD_STRETCH:
7998 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7999 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8001 case Q3TCMOD_TRANSFORM:
8002 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8003 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8004 VectorSet(tcmat + 6, 0 , 0 , 1);
8005 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8006 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8008 case Q3TCMOD_TURBULENT:
8009 // this is handled in the RSurf_PrepareVertices function
8010 matrix = identitymatrix;
8014 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8017 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8019 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8020 char name[MAX_QPATH];
8021 skinframe_t *skinframe;
8022 unsigned char pixels[296*194];
8023 strlcpy(cache->name, skinname, sizeof(cache->name));
8024 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8025 if (developer_loading.integer)
8026 Con_Printf("loading %s\n", name);
8027 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8028 if (!skinframe || !skinframe->base)
8031 fs_offset_t filesize;
8033 f = FS_LoadFile(name, tempmempool, true, &filesize);
8036 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8037 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8041 cache->skinframe = skinframe;
8044 texture_t *R_GetCurrentTexture(texture_t *t)
8047 const entity_render_t *ent = rsurface.entity;
8048 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8049 q3shaderinfo_layer_tcmod_t *tcmod;
8050 float specularscale = 0.0f;
8052 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8053 return t->currentframe;
8054 t->update_lastrenderframe = r_textureframe;
8055 t->update_lastrenderentity = (void *)ent;
8057 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8058 t->camera_entity = ent->entitynumber;
8060 t->camera_entity = 0;
8062 // switch to an alternate material if this is a q1bsp animated material
8064 texture_t *texture = t;
8065 int s = rsurface.ent_skinnum;
8066 if ((unsigned int)s >= (unsigned int)model->numskins)
8068 if (model->skinscenes)
8070 if (model->skinscenes[s].framecount > 1)
8071 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8073 s = model->skinscenes[s].firstframe;
8076 t = t + s * model->num_surfaces;
8079 // use an alternate animation if the entity's frame is not 0,
8080 // and only if the texture has an alternate animation
8081 if (t->animated == 2) // q2bsp
8082 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8083 else if (rsurface.ent_alttextures && t->anim_total[1])
8084 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8086 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8088 texture->currentframe = t;
8091 // update currentskinframe to be a qw skin or animation frame
8092 if (rsurface.ent_qwskin >= 0)
8094 i = rsurface.ent_qwskin;
8095 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8097 r_qwskincache_size = cl.maxclients;
8099 Mem_Free(r_qwskincache);
8100 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8102 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8103 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8104 t->currentskinframe = r_qwskincache[i].skinframe;
8105 if (t->materialshaderpass && t->currentskinframe == NULL)
8106 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8108 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8109 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8110 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8111 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8113 t->currentmaterialflags = t->basematerialflags;
8114 t->currentalpha = rsurface.entity->alpha * t->basealpha;
8115 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8116 t->currentalpha *= r_wateralpha.value;
8117 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8118 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8119 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8120 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8122 // decide on which type of lighting to use for this surface
8123 if (rsurface.entity->render_modellight_forced)
8124 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8125 if (rsurface.entity->render_rtlight_disabled)
8126 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
8127 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
8129 // some CUSTOMBLEND blendfuncs are too weird for anything but fullbright rendering, and even then we have to ignore colormod and view colorscale
8130 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NORTLIGHT;
8131 for (q = 0; q < 3; q++)
8133 t->render_glowmod[q] = rsurface.entity->glowmod[q];
8134 t->render_modellight_lightdir[q] = q == 2;
8135 t->render_modellight_ambient[q] = 1;
8136 t->render_modellight_diffuse[q] = 0;
8137 t->render_modellight_specular[q] = 0;
8138 t->render_lightmap_ambient[q] = 0;
8139 t->render_lightmap_diffuse[q] = 0;
8140 t->render_lightmap_specular[q] = 0;
8141 t->render_rtlight_diffuse[q] = 0;
8142 t->render_rtlight_specular[q] = 0;
8145 else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8147 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8148 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8149 for (q = 0; q < 3; q++)
8151 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8152 t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8153 t->render_modellight_lightdir[q] = q == 2;
8154 t->render_modellight_diffuse[q] = 0;
8155 t->render_modellight_specular[q] = 0;
8156 t->render_lightmap_ambient[q] = 0;
8157 t->render_lightmap_diffuse[q] = 0;
8158 t->render_lightmap_specular[q] = 0;
8159 t->render_rtlight_diffuse[q] = 0;
8160 t->render_rtlight_specular[q] = 0;
8163 else if (FAKELIGHT_ENABLED)
8165 // no modellight if using fakelight for the map
8166 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8167 for (q = 0; q < 3; q++)
8169 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8170 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8171 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8172 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8173 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8174 t->render_lightmap_ambient[q] = 0;
8175 t->render_lightmap_diffuse[q] = 0;
8176 t->render_lightmap_specular[q] = 0;
8177 t->render_rtlight_diffuse[q] = 0;
8178 t->render_rtlight_specular[q] = 0;
8181 else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8183 // ambient + single direction light (modellight)
8184 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8185 for (q = 0; q < 3; q++)
8187 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8188 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8189 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8190 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8191 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8192 t->render_lightmap_ambient[q] = 0;
8193 t->render_lightmap_diffuse[q] = 0;
8194 t->render_lightmap_specular[q] = 0;
8195 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8196 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8201 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8202 for (q = 0; q < 3; q++)
8204 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8205 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q] * r_refdef.view.colorscale;
8206 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8207 t->render_modellight_diffuse[q] = 0;
8208 t->render_modellight_specular[q] = 0;
8209 t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8210 t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8211 t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8212 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8213 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8217 for (q = 0; q < 3; q++)
8219 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8220 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8223 if (rsurface.ent_flags & RENDER_ADDITIVE)
8224 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8225 else if (t->currentalpha < 1)
8226 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8227 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8228 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8229 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8230 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8231 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8232 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8233 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8234 if (t->backgroundshaderpass)
8235 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8236 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8238 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8239 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8242 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8243 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8245 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8246 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8248 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8249 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8251 // there is no tcmod
8252 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8254 t->currenttexmatrix = r_waterscrollmatrix;
8255 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8257 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8259 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8260 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8263 if (t->materialshaderpass)
8264 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8265 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8267 t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8268 if (t->currentskinframe->qpixels)
8269 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8270 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8271 if (!t->basetexture)
8272 t->basetexture = r_texture_notexture;
8273 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8274 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8275 t->nmaptexture = t->currentskinframe->nmap;
8276 if (!t->nmaptexture)
8277 t->nmaptexture = r_texture_blanknormalmap;
8278 t->glosstexture = r_texture_black;
8279 t->glowtexture = t->currentskinframe->glow;
8280 t->fogtexture = t->currentskinframe->fog;
8281 t->reflectmasktexture = t->currentskinframe->reflect;
8282 if (t->backgroundshaderpass)
8284 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8285 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8286 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8287 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8288 t->backgroundglosstexture = r_texture_black;
8289 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8290 if (!t->backgroundnmaptexture)
8291 t->backgroundnmaptexture = r_texture_blanknormalmap;
8292 // make sure that if glow is going to be used, both textures are not NULL
8293 if (!t->backgroundglowtexture && t->glowtexture)
8294 t->backgroundglowtexture = r_texture_black;
8295 if (!t->glowtexture && t->backgroundglowtexture)
8296 t->glowtexture = r_texture_black;
8300 t->backgroundbasetexture = r_texture_white;
8301 t->backgroundnmaptexture = r_texture_blanknormalmap;
8302 t->backgroundglosstexture = r_texture_black;
8303 t->backgroundglowtexture = NULL;
8305 t->specularpower = r_shadow_glossexponent.value;
8306 // TODO: store reference values for these in the texture?
8307 if (r_shadow_gloss.integer > 0)
8309 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8311 if (r_shadow_glossintensity.value > 0)
8313 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8314 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8315 specularscale = r_shadow_glossintensity.value;
8318 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8320 t->glosstexture = r_texture_white;
8321 t->backgroundglosstexture = r_texture_white;
8322 specularscale = r_shadow_gloss2intensity.value;
8323 t->specularpower = r_shadow_gloss2exponent.value;
8326 specularscale *= t->specularscalemod;
8327 t->specularpower *= t->specularpowermod;
8329 // lightmaps mode looks bad with dlights using actual texturing, so turn
8330 // off the colormap and glossmap, but leave the normalmap on as it still
8331 // accurately represents the shading involved
8332 if (gl_lightmaps.integer)
8334 t->basetexture = r_texture_grey128;
8335 t->pantstexture = r_texture_black;
8336 t->shirttexture = r_texture_black;
8337 if (gl_lightmaps.integer < 2)
8338 t->nmaptexture = r_texture_blanknormalmap;
8339 t->glosstexture = r_texture_black;
8340 t->glowtexture = NULL;
8341 t->fogtexture = NULL;
8342 t->reflectmasktexture = NULL;
8343 t->backgroundbasetexture = NULL;
8344 if (gl_lightmaps.integer < 2)
8345 t->backgroundnmaptexture = r_texture_blanknormalmap;
8346 t->backgroundglosstexture = r_texture_black;
8347 t->backgroundglowtexture = NULL;
8349 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8352 if (specularscale != 1.0f)
8354 for (q = 0; q < 3; q++)
8356 t->render_modellight_specular[q] *= specularscale;
8357 t->render_lightmap_specular[q] *= specularscale;
8358 t->render_rtlight_specular[q] *= specularscale;
8362 t->currentnumlayers = 0;
8363 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8365 int blendfunc1, blendfunc2;
8367 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8369 blendfunc1 = GL_SRC_ALPHA;
8370 blendfunc2 = GL_ONE;
8372 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8374 blendfunc1 = GL_SRC_ALPHA;
8375 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8377 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8379 blendfunc1 = t->customblendfunc[0];
8380 blendfunc2 = t->customblendfunc[1];
8384 blendfunc1 = GL_ONE;
8385 blendfunc2 = GL_ZERO;
8387 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8388 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8390 // basic lit geometry
8391 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);
8392 // add pants/shirt if needed
8393 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8394 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);
8395 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8396 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);
8400 // basic lit geometry
8401 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);
8402 // add pants/shirt if needed
8403 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8404 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);
8405 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8406 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);
8407 // now add ambient passes if needed
8408 if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8410 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);
8411 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8412 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);
8413 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8414 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);
8417 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8418 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);
8419 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8421 // if this is opaque use alpha blend which will darken the earlier
8424 // if this is an alpha blended material, all the earlier passes
8425 // were darkened by fog already, so we only need to add the fog
8426 // color ontop through the fog mask texture
8428 // if this is an additive blended material, all the earlier passes
8429 // were darkened by fog already, and we should not add fog color
8430 // (because the background was not darkened, there is no fog color
8431 // that was lost behind it).
8432 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);
8439 rsurfacestate_t rsurface;
8441 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8443 dp_model_t *model = ent->model;
8444 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8446 rsurface.entity = (entity_render_t *)ent;
8447 rsurface.skeleton = ent->skeleton;
8448 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8449 rsurface.ent_skinnum = ent->skinnum;
8450 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;
8451 rsurface.ent_flags = ent->flags;
8452 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8453 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8454 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8455 rsurface.matrix = ent->matrix;
8456 rsurface.inversematrix = ent->inversematrix;
8457 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8458 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8459 R_EntityMatrix(&rsurface.matrix);
8460 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8461 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8462 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8463 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8464 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8465 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8466 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8467 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8468 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8469 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8470 if (ent->model->brush.submodel && !prepass)
8472 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8473 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8475 // if the animcache code decided it should use the shader path, skip the deform step
8476 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8477 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8478 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8479 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8480 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8481 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8483 if (ent->animcache_vertex3f)
8485 r_refdef.stats[r_stat_batch_entitycache_count]++;
8486 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8487 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8488 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8489 rsurface.modelvertex3f = ent->animcache_vertex3f;
8490 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8491 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8492 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8493 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8494 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8495 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8496 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8497 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8498 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8499 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8500 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8501 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8502 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8503 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8505 else if (wanttangents)
8507 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8508 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8509 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8510 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8511 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8512 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8513 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8514 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8515 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8516 rsurface.modelvertexmesh = NULL;
8517 rsurface.modelvertexmesh_vertexbuffer = NULL;
8518 rsurface.modelvertexmesh_bufferoffset = 0;
8519 rsurface.modelvertex3f_vertexbuffer = NULL;
8520 rsurface.modelvertex3f_bufferoffset = 0;
8521 rsurface.modelvertex3f_vertexbuffer = 0;
8522 rsurface.modelvertex3f_bufferoffset = 0;
8523 rsurface.modelsvector3f_vertexbuffer = 0;
8524 rsurface.modelsvector3f_bufferoffset = 0;
8525 rsurface.modeltvector3f_vertexbuffer = 0;
8526 rsurface.modeltvector3f_bufferoffset = 0;
8527 rsurface.modelnormal3f_vertexbuffer = 0;
8528 rsurface.modelnormal3f_bufferoffset = 0;
8530 else if (wantnormals)
8532 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8533 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8534 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8535 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8536 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8537 rsurface.modelsvector3f = NULL;
8538 rsurface.modeltvector3f = NULL;
8539 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8540 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8541 rsurface.modelvertexmesh = NULL;
8542 rsurface.modelvertexmesh_vertexbuffer = NULL;
8543 rsurface.modelvertexmesh_bufferoffset = 0;
8544 rsurface.modelvertex3f_vertexbuffer = NULL;
8545 rsurface.modelvertex3f_bufferoffset = 0;
8546 rsurface.modelvertex3f_vertexbuffer = 0;
8547 rsurface.modelvertex3f_bufferoffset = 0;
8548 rsurface.modelsvector3f_vertexbuffer = 0;
8549 rsurface.modelsvector3f_bufferoffset = 0;
8550 rsurface.modeltvector3f_vertexbuffer = 0;
8551 rsurface.modeltvector3f_bufferoffset = 0;
8552 rsurface.modelnormal3f_vertexbuffer = 0;
8553 rsurface.modelnormal3f_bufferoffset = 0;
8557 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8558 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8559 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8560 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8561 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8562 rsurface.modelsvector3f = NULL;
8563 rsurface.modeltvector3f = NULL;
8564 rsurface.modelnormal3f = NULL;
8565 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8566 rsurface.modelvertexmesh = NULL;
8567 rsurface.modelvertexmesh_vertexbuffer = NULL;
8568 rsurface.modelvertexmesh_bufferoffset = 0;
8569 rsurface.modelvertex3f_vertexbuffer = NULL;
8570 rsurface.modelvertex3f_bufferoffset = 0;
8571 rsurface.modelvertex3f_vertexbuffer = 0;
8572 rsurface.modelvertex3f_bufferoffset = 0;
8573 rsurface.modelsvector3f_vertexbuffer = 0;
8574 rsurface.modelsvector3f_bufferoffset = 0;
8575 rsurface.modeltvector3f_vertexbuffer = 0;
8576 rsurface.modeltvector3f_bufferoffset = 0;
8577 rsurface.modelnormal3f_vertexbuffer = 0;
8578 rsurface.modelnormal3f_bufferoffset = 0;
8580 rsurface.modelgeneratedvertex = true;
8584 if (rsurface.entityskeletaltransform3x4)
8586 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8587 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8588 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8589 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8593 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8594 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8595 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8596 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8598 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8599 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8600 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8601 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8602 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8603 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8604 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8605 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8606 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8607 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8608 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8609 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8610 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8611 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8612 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8613 rsurface.modelgeneratedvertex = false;
8615 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8616 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8617 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8618 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8619 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8620 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8621 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8622 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8623 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8624 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8625 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8626 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8627 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8628 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8629 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8630 rsurface.modelelement3i = model->surfmesh.data_element3i;
8631 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8632 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8633 rsurface.modelelement3s = model->surfmesh.data_element3s;
8634 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8635 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8636 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8637 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8638 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8639 rsurface.modelsurfaces = model->data_surfaces;
8640 rsurface.batchgeneratedvertex = false;
8641 rsurface.batchfirstvertex = 0;
8642 rsurface.batchnumvertices = 0;
8643 rsurface.batchfirsttriangle = 0;
8644 rsurface.batchnumtriangles = 0;
8645 rsurface.batchvertex3f = NULL;
8646 rsurface.batchvertex3f_vertexbuffer = NULL;
8647 rsurface.batchvertex3f_bufferoffset = 0;
8648 rsurface.batchsvector3f = NULL;
8649 rsurface.batchsvector3f_vertexbuffer = NULL;
8650 rsurface.batchsvector3f_bufferoffset = 0;
8651 rsurface.batchtvector3f = NULL;
8652 rsurface.batchtvector3f_vertexbuffer = NULL;
8653 rsurface.batchtvector3f_bufferoffset = 0;
8654 rsurface.batchnormal3f = NULL;
8655 rsurface.batchnormal3f_vertexbuffer = NULL;
8656 rsurface.batchnormal3f_bufferoffset = 0;
8657 rsurface.batchlightmapcolor4f = NULL;
8658 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8659 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8660 rsurface.batchtexcoordtexture2f = NULL;
8661 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8662 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8663 rsurface.batchtexcoordlightmap2f = NULL;
8664 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8665 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8666 rsurface.batchskeletalindex4ub = NULL;
8667 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8668 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8669 rsurface.batchskeletalweight4ub = NULL;
8670 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8671 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8672 rsurface.batchvertexmesh = NULL;
8673 rsurface.batchvertexmesh_vertexbuffer = NULL;
8674 rsurface.batchvertexmesh_bufferoffset = 0;
8675 rsurface.batchelement3i = NULL;
8676 rsurface.batchelement3i_indexbuffer = NULL;
8677 rsurface.batchelement3i_bufferoffset = 0;
8678 rsurface.batchelement3s = NULL;
8679 rsurface.batchelement3s_indexbuffer = NULL;
8680 rsurface.batchelement3s_bufferoffset = 0;
8681 rsurface.passcolor4f = NULL;
8682 rsurface.passcolor4f_vertexbuffer = NULL;
8683 rsurface.passcolor4f_bufferoffset = 0;
8684 rsurface.forcecurrenttextureupdate = false;
8687 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)
8689 rsurface.entity = r_refdef.scene.worldentity;
8690 rsurface.skeleton = NULL;
8691 rsurface.ent_skinnum = 0;
8692 rsurface.ent_qwskin = -1;
8693 rsurface.ent_flags = entflags;
8694 rsurface.shadertime = r_refdef.scene.time - shadertime;
8695 rsurface.modelnumvertices = numvertices;
8696 rsurface.modelnumtriangles = numtriangles;
8697 rsurface.matrix = *matrix;
8698 rsurface.inversematrix = *inversematrix;
8699 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8700 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8701 R_EntityMatrix(&rsurface.matrix);
8702 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8703 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8704 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8705 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8706 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8707 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8708 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8709 rsurface.frameblend[0].lerp = 1;
8710 rsurface.ent_alttextures = false;
8711 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8712 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8713 rsurface.entityskeletaltransform3x4 = NULL;
8714 rsurface.entityskeletaltransform3x4buffer = NULL;
8715 rsurface.entityskeletaltransform3x4offset = 0;
8716 rsurface.entityskeletaltransform3x4size = 0;
8717 rsurface.entityskeletalnumtransforms = 0;
8718 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8719 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8720 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8721 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8724 rsurface.modelvertex3f = (float *)vertex3f;
8725 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8726 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8727 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8729 else if (wantnormals)
8731 rsurface.modelvertex3f = (float *)vertex3f;
8732 rsurface.modelsvector3f = NULL;
8733 rsurface.modeltvector3f = NULL;
8734 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8738 rsurface.modelvertex3f = (float *)vertex3f;
8739 rsurface.modelsvector3f = NULL;
8740 rsurface.modeltvector3f = NULL;
8741 rsurface.modelnormal3f = NULL;
8743 rsurface.modelvertexmesh = NULL;
8744 rsurface.modelvertexmesh_vertexbuffer = NULL;
8745 rsurface.modelvertexmesh_bufferoffset = 0;
8746 rsurface.modelvertex3f_vertexbuffer = 0;
8747 rsurface.modelvertex3f_bufferoffset = 0;
8748 rsurface.modelsvector3f_vertexbuffer = 0;
8749 rsurface.modelsvector3f_bufferoffset = 0;
8750 rsurface.modeltvector3f_vertexbuffer = 0;
8751 rsurface.modeltvector3f_bufferoffset = 0;
8752 rsurface.modelnormal3f_vertexbuffer = 0;
8753 rsurface.modelnormal3f_bufferoffset = 0;
8754 rsurface.modelgeneratedvertex = true;
8755 rsurface.modellightmapcolor4f = (float *)color4f;
8756 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8757 rsurface.modellightmapcolor4f_bufferoffset = 0;
8758 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8759 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8760 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8761 rsurface.modeltexcoordlightmap2f = NULL;
8762 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8763 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8764 rsurface.modelskeletalindex4ub = NULL;
8765 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8766 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8767 rsurface.modelskeletalweight4ub = NULL;
8768 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8769 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8770 rsurface.modelelement3i = (int *)element3i;
8771 rsurface.modelelement3i_indexbuffer = NULL;
8772 rsurface.modelelement3i_bufferoffset = 0;
8773 rsurface.modelelement3s = (unsigned short *)element3s;
8774 rsurface.modelelement3s_indexbuffer = NULL;
8775 rsurface.modelelement3s_bufferoffset = 0;
8776 rsurface.modellightmapoffsets = NULL;
8777 rsurface.modelsurfaces = NULL;
8778 rsurface.batchgeneratedvertex = false;
8779 rsurface.batchfirstvertex = 0;
8780 rsurface.batchnumvertices = 0;
8781 rsurface.batchfirsttriangle = 0;
8782 rsurface.batchnumtriangles = 0;
8783 rsurface.batchvertex3f = NULL;
8784 rsurface.batchvertex3f_vertexbuffer = NULL;
8785 rsurface.batchvertex3f_bufferoffset = 0;
8786 rsurface.batchsvector3f = NULL;
8787 rsurface.batchsvector3f_vertexbuffer = NULL;
8788 rsurface.batchsvector3f_bufferoffset = 0;
8789 rsurface.batchtvector3f = NULL;
8790 rsurface.batchtvector3f_vertexbuffer = NULL;
8791 rsurface.batchtvector3f_bufferoffset = 0;
8792 rsurface.batchnormal3f = NULL;
8793 rsurface.batchnormal3f_vertexbuffer = NULL;
8794 rsurface.batchnormal3f_bufferoffset = 0;
8795 rsurface.batchlightmapcolor4f = NULL;
8796 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8797 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8798 rsurface.batchtexcoordtexture2f = NULL;
8799 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8800 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8801 rsurface.batchtexcoordlightmap2f = NULL;
8802 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8803 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8804 rsurface.batchskeletalindex4ub = NULL;
8805 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8806 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8807 rsurface.batchskeletalweight4ub = NULL;
8808 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8809 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8810 rsurface.batchvertexmesh = NULL;
8811 rsurface.batchvertexmesh_vertexbuffer = NULL;
8812 rsurface.batchvertexmesh_bufferoffset = 0;
8813 rsurface.batchelement3i = NULL;
8814 rsurface.batchelement3i_indexbuffer = NULL;
8815 rsurface.batchelement3i_bufferoffset = 0;
8816 rsurface.batchelement3s = NULL;
8817 rsurface.batchelement3s_indexbuffer = NULL;
8818 rsurface.batchelement3s_bufferoffset = 0;
8819 rsurface.passcolor4f = NULL;
8820 rsurface.passcolor4f_vertexbuffer = NULL;
8821 rsurface.passcolor4f_bufferoffset = 0;
8822 rsurface.forcecurrenttextureupdate = true;
8824 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8826 if ((wantnormals || wanttangents) && !normal3f)
8828 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8829 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8831 if (wanttangents && !svector3f)
8833 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8834 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8835 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8840 float RSurf_FogPoint(const float *v)
8842 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8843 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8844 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8845 float FogHeightFade = r_refdef.fogheightfade;
8847 unsigned int fogmasktableindex;
8848 if (r_refdef.fogplaneviewabove)
8849 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8851 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8852 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8853 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8856 float RSurf_FogVertex(const float *v)
8858 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8859 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8860 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8861 float FogHeightFade = rsurface.fogheightfade;
8863 unsigned int fogmasktableindex;
8864 if (r_refdef.fogplaneviewabove)
8865 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8867 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8868 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8869 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8872 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8875 for (i = 0;i < numelements;i++)
8876 outelement3i[i] = inelement3i[i] + adjust;
8879 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8880 extern cvar_t gl_vbo;
8881 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8889 int surfacefirsttriangle;
8890 int surfacenumtriangles;
8891 int surfacefirstvertex;
8892 int surfaceendvertex;
8893 int surfacenumvertices;
8894 int batchnumsurfaces = texturenumsurfaces;
8895 int batchnumvertices;
8896 int batchnumtriangles;
8900 qboolean dynamicvertex;
8903 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8906 q3shaderinfo_deform_t *deform;
8907 const msurface_t *surface, *firstsurface;
8908 r_vertexmesh_t *vertexmesh;
8909 if (!texturenumsurfaces)
8911 // find vertex range of this surface batch
8913 firstsurface = texturesurfacelist[0];
8914 firsttriangle = firstsurface->num_firsttriangle;
8915 batchnumvertices = 0;
8916 batchnumtriangles = 0;
8917 firstvertex = endvertex = firstsurface->num_firstvertex;
8918 for (i = 0;i < texturenumsurfaces;i++)
8920 surface = texturesurfacelist[i];
8921 if (surface != firstsurface + i)
8923 surfacefirstvertex = surface->num_firstvertex;
8924 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8925 surfacenumvertices = surface->num_vertices;
8926 surfacenumtriangles = surface->num_triangles;
8927 if (firstvertex > surfacefirstvertex)
8928 firstvertex = surfacefirstvertex;
8929 if (endvertex < surfaceendvertex)
8930 endvertex = surfaceendvertex;
8931 batchnumvertices += surfacenumvertices;
8932 batchnumtriangles += surfacenumtriangles;
8935 r_refdef.stats[r_stat_batch_batches]++;
8937 r_refdef.stats[r_stat_batch_withgaps]++;
8938 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8939 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8940 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8942 // we now know the vertex range used, and if there are any gaps in it
8943 rsurface.batchfirstvertex = firstvertex;
8944 rsurface.batchnumvertices = endvertex - firstvertex;
8945 rsurface.batchfirsttriangle = firsttriangle;
8946 rsurface.batchnumtriangles = batchnumtriangles;
8948 // this variable holds flags for which properties have been updated that
8949 // may require regenerating vertexmesh array...
8952 // check if any dynamic vertex processing must occur
8953 dynamicvertex = false;
8955 // a cvar to force the dynamic vertex path to be taken, for debugging
8956 if (r_batch_debugdynamicvertexpath.integer)
8960 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8961 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8962 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8963 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8965 dynamicvertex = true;
8968 // if there is a chance of animated vertex colors, it's a dynamic batch
8969 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8973 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8974 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8975 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8976 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8978 dynamicvertex = true;
8979 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8982 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8984 switch (deform->deform)
8987 case Q3DEFORM_PROJECTIONSHADOW:
8988 case Q3DEFORM_TEXT0:
8989 case Q3DEFORM_TEXT1:
8990 case Q3DEFORM_TEXT2:
8991 case Q3DEFORM_TEXT3:
8992 case Q3DEFORM_TEXT4:
8993 case Q3DEFORM_TEXT5:
8994 case Q3DEFORM_TEXT6:
8995 case Q3DEFORM_TEXT7:
8998 case Q3DEFORM_AUTOSPRITE:
9001 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9002 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9003 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9004 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9006 dynamicvertex = true;
9007 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9008 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9010 case Q3DEFORM_AUTOSPRITE2:
9013 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9014 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9015 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9016 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9018 dynamicvertex = true;
9019 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9020 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9022 case Q3DEFORM_NORMAL:
9025 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9026 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9027 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9028 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9030 dynamicvertex = true;
9031 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9032 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9035 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9036 break; // if wavefunc is a nop, ignore this transform
9039 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9040 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9041 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9042 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9044 dynamicvertex = true;
9045 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9046 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9048 case Q3DEFORM_BULGE:
9051 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9052 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9053 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9054 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9056 dynamicvertex = true;
9057 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9058 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9061 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9062 break; // if wavefunc is a nop, ignore this transform
9065 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9066 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9067 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9068 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9070 dynamicvertex = true;
9071 batchneed |= BATCHNEED_ARRAY_VERTEX;
9072 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9076 if (rsurface.texture->materialshaderpass)
9078 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9081 case Q3TCGEN_TEXTURE:
9083 case Q3TCGEN_LIGHTMAP:
9086 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9087 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9088 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9089 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9091 dynamicvertex = true;
9092 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9093 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9095 case Q3TCGEN_VECTOR:
9098 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9099 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9100 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9101 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9103 dynamicvertex = true;
9104 batchneed |= BATCHNEED_ARRAY_VERTEX;
9105 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9107 case Q3TCGEN_ENVIRONMENT:
9110 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9111 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9112 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9113 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9115 dynamicvertex = true;
9116 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9117 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9120 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9124 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9125 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9126 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9127 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9129 dynamicvertex = true;
9130 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9131 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9135 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9139 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9140 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9141 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9142 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9144 dynamicvertex = true;
9145 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9148 // when the model data has no vertex buffer (dynamic mesh), we need to
9150 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9151 batchneed |= BATCHNEED_NOGAPS;
9153 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9154 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9155 // we ensure this by treating the vertex batch as dynamic...
9156 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9160 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9161 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9162 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9163 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9165 dynamicvertex = true;
9170 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9171 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9172 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9173 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9174 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9175 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9176 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9177 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9180 // if needsupdate, we have to do a dynamic vertex batch for sure
9181 if (needsupdate & batchneed)
9185 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9186 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9187 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9188 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9190 dynamicvertex = true;
9193 // see if we need to build vertexmesh from arrays
9194 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9198 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9199 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9200 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9201 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9203 dynamicvertex = true;
9206 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9207 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9208 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9210 rsurface.batchvertex3f = rsurface.modelvertex3f;
9211 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9212 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9213 rsurface.batchsvector3f = rsurface.modelsvector3f;
9214 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9215 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9216 rsurface.batchtvector3f = rsurface.modeltvector3f;
9217 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9218 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9219 rsurface.batchnormal3f = rsurface.modelnormal3f;
9220 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9221 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9222 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9223 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9224 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9225 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9226 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9227 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9228 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9229 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9230 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9231 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9232 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9233 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9234 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9235 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9236 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9237 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9238 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9239 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9240 rsurface.batchelement3i = rsurface.modelelement3i;
9241 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9242 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9243 rsurface.batchelement3s = rsurface.modelelement3s;
9244 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9245 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9246 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9247 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9248 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9249 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9250 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9252 // if any dynamic vertex processing has to occur in software, we copy the
9253 // entire surface list together before processing to rebase the vertices
9254 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9256 // if any gaps exist and we do not have a static vertex buffer, we have to
9257 // copy the surface list together to avoid wasting upload bandwidth on the
9258 // vertices in the gaps.
9260 // if gaps exist and we have a static vertex buffer, we can choose whether
9261 // to combine the index buffer ranges into one dynamic index buffer or
9262 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9264 // in many cases the batch is reduced to one draw call.
9266 rsurface.batchmultidraw = false;
9267 rsurface.batchmultidrawnumsurfaces = 0;
9268 rsurface.batchmultidrawsurfacelist = NULL;
9272 // static vertex data, just set pointers...
9273 rsurface.batchgeneratedvertex = false;
9274 // if there are gaps, we want to build a combined index buffer,
9275 // otherwise use the original static buffer with an appropriate offset
9278 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9279 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9280 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9281 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9282 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9284 rsurface.batchmultidraw = true;
9285 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9286 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9289 // build a new triangle elements array for this batch
9290 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9291 rsurface.batchfirsttriangle = 0;
9293 for (i = 0;i < texturenumsurfaces;i++)
9295 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9296 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9297 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9298 numtriangles += surfacenumtriangles;
9300 rsurface.batchelement3i_indexbuffer = NULL;
9301 rsurface.batchelement3i_bufferoffset = 0;
9302 rsurface.batchelement3s = NULL;
9303 rsurface.batchelement3s_indexbuffer = NULL;
9304 rsurface.batchelement3s_bufferoffset = 0;
9305 if (endvertex <= 65536)
9307 // make a 16bit (unsigned short) index array if possible
9308 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9309 for (i = 0;i < numtriangles*3;i++)
9310 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9312 // upload buffer data for the copytriangles batch
9313 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9315 if (rsurface.batchelement3s)
9316 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9317 else if (rsurface.batchelement3i)
9318 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9323 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9324 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9325 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9326 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9331 // something needs software processing, do it for real...
9332 // we only directly handle separate array data in this case and then
9333 // generate interleaved data if needed...
9334 rsurface.batchgeneratedvertex = true;
9335 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9336 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9337 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9338 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9340 // now copy the vertex data into a combined array and make an index array
9341 // (this is what Quake3 does all the time)
9342 // we also apply any skeletal animation here that would have been done in
9343 // the vertex shader, because most of the dynamic vertex animation cases
9344 // need actual vertex positions and normals
9345 //if (dynamicvertex)
9347 rsurface.batchvertexmesh = NULL;
9348 rsurface.batchvertexmesh_vertexbuffer = NULL;
9349 rsurface.batchvertexmesh_bufferoffset = 0;
9350 rsurface.batchvertex3f = NULL;
9351 rsurface.batchvertex3f_vertexbuffer = NULL;
9352 rsurface.batchvertex3f_bufferoffset = 0;
9353 rsurface.batchsvector3f = NULL;
9354 rsurface.batchsvector3f_vertexbuffer = NULL;
9355 rsurface.batchsvector3f_bufferoffset = 0;
9356 rsurface.batchtvector3f = NULL;
9357 rsurface.batchtvector3f_vertexbuffer = NULL;
9358 rsurface.batchtvector3f_bufferoffset = 0;
9359 rsurface.batchnormal3f = NULL;
9360 rsurface.batchnormal3f_vertexbuffer = NULL;
9361 rsurface.batchnormal3f_bufferoffset = 0;
9362 rsurface.batchlightmapcolor4f = NULL;
9363 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9364 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9365 rsurface.batchtexcoordtexture2f = NULL;
9366 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9367 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9368 rsurface.batchtexcoordlightmap2f = NULL;
9369 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9370 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9371 rsurface.batchskeletalindex4ub = NULL;
9372 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9373 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9374 rsurface.batchskeletalweight4ub = NULL;
9375 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9376 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9377 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9378 rsurface.batchelement3i_indexbuffer = NULL;
9379 rsurface.batchelement3i_bufferoffset = 0;
9380 rsurface.batchelement3s = NULL;
9381 rsurface.batchelement3s_indexbuffer = NULL;
9382 rsurface.batchelement3s_bufferoffset = 0;
9383 rsurface.batchskeletaltransform3x4buffer = NULL;
9384 rsurface.batchskeletaltransform3x4offset = 0;
9385 rsurface.batchskeletaltransform3x4size = 0;
9386 // we'll only be setting up certain arrays as needed
9387 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9388 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9389 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9390 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9391 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9392 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9393 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9395 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9396 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9398 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9399 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9400 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9401 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9402 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9403 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9404 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9406 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9407 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9411 for (i = 0;i < texturenumsurfaces;i++)
9413 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9414 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9415 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9416 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9417 // copy only the data requested
9418 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9419 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9420 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9422 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9424 if (rsurface.batchvertex3f)
9425 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9427 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9429 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9431 if (rsurface.modelnormal3f)
9432 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9434 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9436 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9438 if (rsurface.modelsvector3f)
9440 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9441 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9445 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9446 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9449 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9451 if (rsurface.modellightmapcolor4f)
9452 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9454 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9456 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9458 if (rsurface.modeltexcoordtexture2f)
9459 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9461 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9463 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9465 if (rsurface.modeltexcoordlightmap2f)
9466 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9468 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9470 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9472 if (rsurface.modelskeletalindex4ub)
9474 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9475 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9479 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9480 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9481 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9482 for (j = 0;j < surfacenumvertices;j++)
9487 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9488 numvertices += surfacenumvertices;
9489 numtriangles += surfacenumtriangles;
9492 // generate a 16bit index array as well if possible
9493 // (in general, dynamic batches fit)
9494 if (numvertices <= 65536)
9496 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9497 for (i = 0;i < numtriangles*3;i++)
9498 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9501 // since we've copied everything, the batch now starts at 0
9502 rsurface.batchfirstvertex = 0;
9503 rsurface.batchnumvertices = batchnumvertices;
9504 rsurface.batchfirsttriangle = 0;
9505 rsurface.batchnumtriangles = batchnumtriangles;
9508 // apply skeletal animation that would have been done in the vertex shader
9509 if (rsurface.batchskeletaltransform3x4)
9511 const unsigned char *si;
9512 const unsigned char *sw;
9514 const float *b = rsurface.batchskeletaltransform3x4;
9515 float *vp, *vs, *vt, *vn;
9517 float m[3][4], n[3][4];
9518 float tp[3], ts[3], tt[3], tn[3];
9519 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9520 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9521 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9522 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9523 si = rsurface.batchskeletalindex4ub;
9524 sw = rsurface.batchskeletalweight4ub;
9525 vp = rsurface.batchvertex3f;
9526 vs = rsurface.batchsvector3f;
9527 vt = rsurface.batchtvector3f;
9528 vn = rsurface.batchnormal3f;
9529 memset(m[0], 0, sizeof(m));
9530 memset(n[0], 0, sizeof(n));
9531 for (i = 0;i < batchnumvertices;i++)
9533 t[0] = b + si[0]*12;
9536 // common case - only one matrix
9550 else if (sw[2] + sw[3])
9553 t[1] = b + si[1]*12;
9554 t[2] = b + si[2]*12;
9555 t[3] = b + si[3]*12;
9556 w[0] = sw[0] * (1.0f / 255.0f);
9557 w[1] = sw[1] * (1.0f / 255.0f);
9558 w[2] = sw[2] * (1.0f / 255.0f);
9559 w[3] = sw[3] * (1.0f / 255.0f);
9560 // blend the matrices
9561 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9562 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9563 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9564 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9565 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9566 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9567 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9568 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9569 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9570 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9571 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9572 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9577 t[1] = b + si[1]*12;
9578 w[0] = sw[0] * (1.0f / 255.0f);
9579 w[1] = sw[1] * (1.0f / 255.0f);
9580 // blend the matrices
9581 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9582 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9583 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9584 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9585 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9586 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9587 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9588 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9589 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9590 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9591 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9592 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9596 // modify the vertex
9598 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9599 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9600 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9604 // the normal transformation matrix is a set of cross products...
9605 CrossProduct(m[1], m[2], n[0]);
9606 CrossProduct(m[2], m[0], n[1]);
9607 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9609 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9610 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9611 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9612 VectorNormalize(vn);
9617 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9618 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9619 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9620 VectorNormalize(vs);
9623 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9624 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9625 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9626 VectorNormalize(vt);
9631 rsurface.batchskeletaltransform3x4 = NULL;
9632 rsurface.batchskeletalnumtransforms = 0;
9635 // q1bsp surfaces rendered in vertex color mode have to have colors
9636 // calculated based on lightstyles
9637 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9639 // generate color arrays for the surfaces in this list
9644 const unsigned char *lm;
9645 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9646 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9647 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9649 for (i = 0;i < texturenumsurfaces;i++)
9651 surface = texturesurfacelist[i];
9652 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9653 surfacenumvertices = surface->num_vertices;
9654 if (surface->lightmapinfo->samples)
9656 for (j = 0;j < surfacenumvertices;j++)
9658 lm = surface->lightmapinfo->samples + offsets[j];
9659 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9660 VectorScale(lm, scale, c);
9661 if (surface->lightmapinfo->styles[1] != 255)
9663 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9665 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9666 VectorMA(c, scale, lm, c);
9667 if (surface->lightmapinfo->styles[2] != 255)
9670 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9671 VectorMA(c, scale, lm, c);
9672 if (surface->lightmapinfo->styles[3] != 255)
9675 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9676 VectorMA(c, scale, lm, c);
9683 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);
9689 for (j = 0;j < surfacenumvertices;j++)
9691 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9698 // if vertices are deformed (sprite flares and things in maps, possibly
9699 // water waves, bulges and other deformations), modify the copied vertices
9701 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9704 switch (deform->deform)
9707 case Q3DEFORM_PROJECTIONSHADOW:
9708 case Q3DEFORM_TEXT0:
9709 case Q3DEFORM_TEXT1:
9710 case Q3DEFORM_TEXT2:
9711 case Q3DEFORM_TEXT3:
9712 case Q3DEFORM_TEXT4:
9713 case Q3DEFORM_TEXT5:
9714 case Q3DEFORM_TEXT6:
9715 case Q3DEFORM_TEXT7:
9718 case Q3DEFORM_AUTOSPRITE:
9719 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9720 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9721 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9722 VectorNormalize(newforward);
9723 VectorNormalize(newright);
9724 VectorNormalize(newup);
9725 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9726 // rsurface.batchvertex3f_vertexbuffer = NULL;
9727 // rsurface.batchvertex3f_bufferoffset = 0;
9728 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9729 // rsurface.batchsvector3f_vertexbuffer = NULL;
9730 // rsurface.batchsvector3f_bufferoffset = 0;
9731 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9732 // rsurface.batchtvector3f_vertexbuffer = NULL;
9733 // rsurface.batchtvector3f_bufferoffset = 0;
9734 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9735 // rsurface.batchnormal3f_vertexbuffer = NULL;
9736 // rsurface.batchnormal3f_bufferoffset = 0;
9737 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9738 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9739 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9740 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9741 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);
9742 // a single autosprite surface can contain multiple sprites...
9743 for (j = 0;j < batchnumvertices - 3;j += 4)
9745 VectorClear(center);
9746 for (i = 0;i < 4;i++)
9747 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9748 VectorScale(center, 0.25f, center);
9749 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9750 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9751 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9752 for (i = 0;i < 4;i++)
9754 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9755 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9758 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9759 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9760 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);
9762 case Q3DEFORM_AUTOSPRITE2:
9763 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9764 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9765 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9766 VectorNormalize(newforward);
9767 VectorNormalize(newright);
9768 VectorNormalize(newup);
9769 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9770 // rsurface.batchvertex3f_vertexbuffer = NULL;
9771 // rsurface.batchvertex3f_bufferoffset = 0;
9773 const float *v1, *v2;
9783 memset(shortest, 0, sizeof(shortest));
9784 // a single autosprite surface can contain multiple sprites...
9785 for (j = 0;j < batchnumvertices - 3;j += 4)
9787 VectorClear(center);
9788 for (i = 0;i < 4;i++)
9789 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9790 VectorScale(center, 0.25f, center);
9791 // find the two shortest edges, then use them to define the
9792 // axis vectors for rotating around the central axis
9793 for (i = 0;i < 6;i++)
9795 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9796 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9797 l = VectorDistance2(v1, v2);
9798 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9800 l += (1.0f / 1024.0f);
9801 if (shortest[0].length2 > l || i == 0)
9803 shortest[1] = shortest[0];
9804 shortest[0].length2 = l;
9805 shortest[0].v1 = v1;
9806 shortest[0].v2 = v2;
9808 else if (shortest[1].length2 > l || i == 1)
9810 shortest[1].length2 = l;
9811 shortest[1].v1 = v1;
9812 shortest[1].v2 = v2;
9815 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9816 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9817 // this calculates the right vector from the shortest edge
9818 // and the up vector from the edge midpoints
9819 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9820 VectorNormalize(right);
9821 VectorSubtract(end, start, up);
9822 VectorNormalize(up);
9823 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9824 VectorSubtract(rsurface.localvieworigin, center, forward);
9825 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9826 VectorNegate(forward, forward);
9827 VectorReflect(forward, 0, up, forward);
9828 VectorNormalize(forward);
9829 CrossProduct(up, forward, newright);
9830 VectorNormalize(newright);
9831 // rotate the quad around the up axis vector, this is made
9832 // especially easy by the fact we know the quad is flat,
9833 // so we only have to subtract the center position and
9834 // measure distance along the right vector, and then
9835 // multiply that by the newright vector and add back the
9837 // we also need to subtract the old position to undo the
9838 // displacement from the center, which we do with a
9839 // DotProduct, the subtraction/addition of center is also
9840 // optimized into DotProducts here
9841 l = DotProduct(right, center);
9842 for (i = 0;i < 4;i++)
9844 v1 = rsurface.batchvertex3f + 3*(j+i);
9845 f = DotProduct(right, v1) - l;
9846 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9850 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9852 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9853 // rsurface.batchnormal3f_vertexbuffer = NULL;
9854 // rsurface.batchnormal3f_bufferoffset = 0;
9855 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9857 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9859 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9860 // rsurface.batchsvector3f_vertexbuffer = NULL;
9861 // rsurface.batchsvector3f_bufferoffset = 0;
9862 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9863 // rsurface.batchtvector3f_vertexbuffer = NULL;
9864 // rsurface.batchtvector3f_bufferoffset = 0;
9865 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);
9868 case Q3DEFORM_NORMAL:
9869 // deform the normals to make reflections wavey
9870 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9871 rsurface.batchnormal3f_vertexbuffer = NULL;
9872 rsurface.batchnormal3f_bufferoffset = 0;
9873 for (j = 0;j < batchnumvertices;j++)
9876 float *normal = rsurface.batchnormal3f + 3*j;
9877 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9878 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9879 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9880 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9881 VectorNormalize(normal);
9883 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9885 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9886 // rsurface.batchsvector3f_vertexbuffer = NULL;
9887 // rsurface.batchsvector3f_bufferoffset = 0;
9888 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9889 // rsurface.batchtvector3f_vertexbuffer = NULL;
9890 // rsurface.batchtvector3f_bufferoffset = 0;
9891 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9895 // deform vertex array to make wavey water and flags and such
9896 waveparms[0] = deform->waveparms[0];
9897 waveparms[1] = deform->waveparms[1];
9898 waveparms[2] = deform->waveparms[2];
9899 waveparms[3] = deform->waveparms[3];
9900 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9901 break; // if wavefunc is a nop, don't make a dynamic vertex array
9902 // this is how a divisor of vertex influence on deformation
9903 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9904 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9905 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9906 // rsurface.batchvertex3f_vertexbuffer = NULL;
9907 // rsurface.batchvertex3f_bufferoffset = 0;
9908 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9909 // rsurface.batchnormal3f_vertexbuffer = NULL;
9910 // rsurface.batchnormal3f_bufferoffset = 0;
9911 for (j = 0;j < batchnumvertices;j++)
9913 // if the wavefunc depends on time, evaluate it per-vertex
9916 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9917 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9919 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9921 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9922 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9923 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9925 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9926 // rsurface.batchsvector3f_vertexbuffer = NULL;
9927 // rsurface.batchsvector3f_bufferoffset = 0;
9928 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9929 // rsurface.batchtvector3f_vertexbuffer = NULL;
9930 // rsurface.batchtvector3f_bufferoffset = 0;
9931 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);
9934 case Q3DEFORM_BULGE:
9935 // deform vertex array to make the surface have moving bulges
9936 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9937 // rsurface.batchvertex3f_vertexbuffer = NULL;
9938 // rsurface.batchvertex3f_bufferoffset = 0;
9939 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9940 // rsurface.batchnormal3f_vertexbuffer = NULL;
9941 // rsurface.batchnormal3f_bufferoffset = 0;
9942 for (j = 0;j < batchnumvertices;j++)
9944 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9945 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9947 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9948 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9949 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9951 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9952 // rsurface.batchsvector3f_vertexbuffer = NULL;
9953 // rsurface.batchsvector3f_bufferoffset = 0;
9954 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9955 // rsurface.batchtvector3f_vertexbuffer = NULL;
9956 // rsurface.batchtvector3f_bufferoffset = 0;
9957 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);
9961 // deform vertex array
9962 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9963 break; // if wavefunc is a nop, don't make a dynamic vertex array
9964 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9965 VectorScale(deform->parms, scale, waveparms);
9966 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9967 // rsurface.batchvertex3f_vertexbuffer = NULL;
9968 // rsurface.batchvertex3f_bufferoffset = 0;
9969 for (j = 0;j < batchnumvertices;j++)
9970 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9975 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9977 // generate texcoords based on the chosen texcoord source
9978 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9981 case Q3TCGEN_TEXTURE:
9983 case Q3TCGEN_LIGHTMAP:
9984 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9985 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9986 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9987 if (rsurface.batchtexcoordlightmap2f)
9988 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9990 case Q3TCGEN_VECTOR:
9991 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9992 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9993 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9994 for (j = 0;j < batchnumvertices;j++)
9996 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9997 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10000 case Q3TCGEN_ENVIRONMENT:
10001 // make environment reflections using a spheremap
10002 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10003 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10004 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10005 for (j = 0;j < batchnumvertices;j++)
10007 // identical to Q3A's method, but executed in worldspace so
10008 // carried models can be shiny too
10010 float viewer[3], d, reflected[3], worldreflected[3];
10012 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10013 // VectorNormalize(viewer);
10015 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10017 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10018 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10019 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10020 // note: this is proportinal to viewer, so we can normalize later
10022 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10023 VectorNormalize(worldreflected);
10025 // note: this sphere map only uses world x and z!
10026 // so positive and negative y will LOOK THE SAME.
10027 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10028 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10032 // the only tcmod that needs software vertex processing is turbulent, so
10033 // check for it here and apply the changes if needed
10034 // and we only support that as the first one
10035 // (handling a mixture of turbulent and other tcmods would be problematic
10036 // without punting it entirely to a software path)
10037 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10039 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10040 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10041 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10042 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10043 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10044 for (j = 0;j < batchnumvertices;j++)
10046 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);
10047 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10052 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10054 // convert the modified arrays to vertex structs
10055 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10056 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10057 // rsurface.batchvertexmesh_bufferoffset = 0;
10058 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10059 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10060 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10061 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10062 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10063 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10064 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10066 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10068 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10069 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10072 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10073 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10074 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10075 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10076 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10077 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10078 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10079 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10080 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10081 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10083 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10085 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10086 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10091 // upload buffer data for the dynamic batch
10092 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10094 if (rsurface.batchvertexmesh)
10095 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10098 if (rsurface.batchvertex3f)
10099 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10100 if (rsurface.batchsvector3f)
10101 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10102 if (rsurface.batchtvector3f)
10103 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10104 if (rsurface.batchnormal3f)
10105 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10106 if (rsurface.batchlightmapcolor4f)
10107 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10108 if (rsurface.batchtexcoordtexture2f)
10109 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10110 if (rsurface.batchtexcoordlightmap2f)
10111 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10112 if (rsurface.batchskeletalindex4ub)
10113 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10114 if (rsurface.batchskeletalweight4ub)
10115 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10117 if (rsurface.batchelement3s)
10118 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10119 else if (rsurface.batchelement3i)
10120 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10124 void RSurf_DrawBatch(void)
10126 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10127 // through the pipeline, killing it earlier in the pipeline would have
10128 // per-surface overhead rather than per-batch overhead, so it's best to
10129 // reject it here, before it hits glDraw.
10130 if (rsurface.batchnumtriangles == 0)
10133 // batch debugging code
10134 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10140 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10141 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10144 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10146 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10148 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10149 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);
10156 if (rsurface.batchmultidraw)
10158 // issue multiple draws rather than copying index data
10159 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10160 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10161 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10162 for (i = 0;i < numsurfaces;)
10164 // combine consecutive surfaces as one draw
10165 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10166 if (surfacelist[j] != surfacelist[k] + 1)
10168 firstvertex = surfacelist[i]->num_firstvertex;
10169 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10170 firsttriangle = surfacelist[i]->num_firsttriangle;
10171 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10172 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);
10178 // there is only one consecutive run of index data (may have been combined)
10179 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);
10183 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10185 // pick the closest matching water plane
10186 int planeindex, vertexindex, bestplaneindex = -1;
10190 r_waterstate_waterplane_t *p;
10191 qboolean prepared = false;
10193 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10195 if(p->camera_entity != rsurface.texture->camera_entity)
10200 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10202 if(rsurface.batchnumvertices == 0)
10205 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10207 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10208 d += fabs(PlaneDiff(vert, &p->plane));
10210 if (bestd > d || bestplaneindex < 0)
10213 bestplaneindex = planeindex;
10216 return bestplaneindex;
10217 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10218 // this situation though, as it might be better to render single larger
10219 // batches with useless stuff (backface culled for example) than to
10220 // render multiple smaller batches
10223 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10226 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10227 rsurface.passcolor4f_vertexbuffer = 0;
10228 rsurface.passcolor4f_bufferoffset = 0;
10229 for (i = 0;i < rsurface.batchnumvertices;i++)
10230 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10233 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10240 if (rsurface.passcolor4f)
10242 // generate color arrays
10243 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10244 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10245 rsurface.passcolor4f_vertexbuffer = 0;
10246 rsurface.passcolor4f_bufferoffset = 0;
10247 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)
10249 f = RSurf_FogVertex(v);
10258 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10259 rsurface.passcolor4f_vertexbuffer = 0;
10260 rsurface.passcolor4f_bufferoffset = 0;
10261 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10263 f = RSurf_FogVertex(v);
10272 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10279 if (!rsurface.passcolor4f)
10281 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10282 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10283 rsurface.passcolor4f_vertexbuffer = 0;
10284 rsurface.passcolor4f_bufferoffset = 0;
10285 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)
10287 f = RSurf_FogVertex(v);
10288 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10289 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10290 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10295 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10300 if (!rsurface.passcolor4f)
10302 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10303 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10304 rsurface.passcolor4f_vertexbuffer = 0;
10305 rsurface.passcolor4f_bufferoffset = 0;
10306 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10315 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10320 if (!rsurface.passcolor4f)
10322 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10323 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10324 rsurface.passcolor4f_vertexbuffer = 0;
10325 rsurface.passcolor4f_bufferoffset = 0;
10326 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10328 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10329 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10330 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10335 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10338 rsurface.passcolor4f = NULL;
10339 rsurface.passcolor4f_vertexbuffer = 0;
10340 rsurface.passcolor4f_bufferoffset = 0;
10341 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10342 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10343 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10344 GL_Color(r, g, b, a);
10345 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10346 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10347 R_Mesh_TexMatrix(0, NULL);
10351 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10353 // TODO: optimize applyfog && applycolor case
10354 // just apply fog if necessary, and tint the fog color array if necessary
10355 rsurface.passcolor4f = NULL;
10356 rsurface.passcolor4f_vertexbuffer = 0;
10357 rsurface.passcolor4f_bufferoffset = 0;
10358 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10359 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10360 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10361 GL_Color(r, g, b, a);
10365 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10368 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10369 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10370 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10371 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10372 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10373 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10374 GL_Color(r, g, b, a);
10378 static void RSurf_DrawBatch_GL11_ClampColor(void)
10383 if (!rsurface.passcolor4f)
10385 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10387 c2[0] = bound(0.0f, c1[0], 1.0f);
10388 c2[1] = bound(0.0f, c1[1], 1.0f);
10389 c2[2] = bound(0.0f, c1[2], 1.0f);
10390 c2[3] = bound(0.0f, c1[3], 1.0f);
10394 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10404 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10405 rsurface.passcolor4f_vertexbuffer = 0;
10406 rsurface.passcolor4f_bufferoffset = 0;
10407 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)
10409 f = -DotProduct(r_refdef.view.forward, n);
10411 f = f * 0.85 + 0.15; // work around so stuff won't get black
10412 f *= fakelightintensity;
10413 Vector4Set(c, f, f, f, 1);
10417 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10419 RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10420 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10421 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10422 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10423 GL_Color(r, g, b, a);
10427 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10435 vec3_t ambientcolor;
10436 vec3_t diffusecolor;
10440 VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10441 f = 0.5f * lightmapintensity;
10442 ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10443 ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10444 ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10445 diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10446 diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10447 diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10449 if (VectorLength2(diffusecolor) > 0)
10451 // q3-style directional shading
10452 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10453 rsurface.passcolor4f_vertexbuffer = 0;
10454 rsurface.passcolor4f_bufferoffset = 0;
10455 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)
10457 if ((f = DotProduct(n, lightdir)) > 0)
10458 VectorMA(ambientcolor, f, diffusecolor, c);
10460 VectorCopy(ambientcolor, c);
10467 *applycolor = false;
10471 *r = ambientcolor[0];
10472 *g = ambientcolor[1];
10473 *b = ambientcolor[2];
10474 rsurface.passcolor4f = NULL;
10475 rsurface.passcolor4f_vertexbuffer = 0;
10476 rsurface.passcolor4f_bufferoffset = 0;
10480 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10482 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10483 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10484 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10485 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10486 GL_Color(r, g, b, a);
10490 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10498 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10499 rsurface.passcolor4f_vertexbuffer = 0;
10500 rsurface.passcolor4f_bufferoffset = 0;
10502 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10504 f = 1 - RSurf_FogVertex(v);
10512 void RSurf_SetupDepthAndCulling(void)
10514 // submodels are biased to avoid z-fighting with world surfaces that they
10515 // may be exactly overlapping (avoids z-fighting artifacts on certain
10516 // doors and things in Quake maps)
10517 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10518 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10519 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10520 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10523 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10525 // transparent sky would be ridiculous
10526 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10528 R_SetupShader_Generic_NoTexture(false, false);
10529 skyrenderlater = true;
10530 RSurf_SetupDepthAndCulling();
10531 GL_DepthMask(true);
10532 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10533 // skymasking on them, and Quake3 never did sky masking (unlike
10534 // software Quake and software Quake2), so disable the sky masking
10535 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10536 // and skymasking also looks very bad when noclipping outside the
10537 // level, so don't use it then either.
10538 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10540 R_Mesh_ResetTextureState();
10541 if (skyrendermasked)
10543 R_SetupShader_DepthOrShadow(false, false, false);
10544 // depth-only (masking)
10545 GL_ColorMask(0,0,0,0);
10546 // just to make sure that braindead drivers don't draw
10547 // anything despite that colormask...
10548 GL_BlendFunc(GL_ZERO, GL_ONE);
10549 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10550 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10554 R_SetupShader_Generic_NoTexture(false, false);
10556 GL_BlendFunc(GL_ONE, GL_ZERO);
10557 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10558 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10559 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10562 if (skyrendermasked)
10563 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10565 R_Mesh_ResetTextureState();
10566 GL_Color(1, 1, 1, 1);
10569 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10570 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10571 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10573 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10577 // render screenspace normalmap to texture
10578 GL_DepthMask(true);
10579 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10584 // bind lightmap texture
10586 // water/refraction/reflection/camera surfaces have to be handled specially
10587 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10589 int start, end, startplaneindex;
10590 for (start = 0;start < texturenumsurfaces;start = end)
10592 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10593 if(startplaneindex < 0)
10595 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10596 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10600 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10602 // now that we have a batch using the same planeindex, render it
10603 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10605 // render water or distortion background
10606 GL_DepthMask(true);
10607 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10609 // blend surface on top
10610 GL_DepthMask(false);
10611 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10614 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10616 // render surface with reflection texture as input
10617 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10618 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10625 // render surface batch normally
10626 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10627 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10631 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10633 // OpenGL 1.3 path - anything not completely ancient
10634 qboolean applycolor;
10637 const texturelayer_t *layer;
10638 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);
10639 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10641 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10644 int layertexrgbscale;
10645 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10647 if (layerindex == 0)
10648 GL_AlphaTest(true);
10651 GL_AlphaTest(false);
10652 GL_DepthFunc(GL_EQUAL);
10655 GL_DepthMask(layer->depthmask && writedepth);
10656 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10657 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10659 layertexrgbscale = 4;
10660 VectorScale(layer->color, 0.25f, layercolor);
10662 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10664 layertexrgbscale = 2;
10665 VectorScale(layer->color, 0.5f, layercolor);
10669 layertexrgbscale = 1;
10670 VectorScale(layer->color, 1.0f, layercolor);
10672 layercolor[3] = layer->color[3];
10673 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10674 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10675 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10676 switch (layer->type)
10678 case TEXTURELAYERTYPE_LITTEXTURE:
10679 // single-pass lightmapped texture with 2x rgbscale
10680 R_Mesh_TexBind(0, r_texture_white);
10681 R_Mesh_TexMatrix(0, NULL);
10682 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10683 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10684 R_Mesh_TexBind(1, layer->texture);
10685 R_Mesh_TexMatrix(1, &layer->texmatrix);
10686 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10687 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10688 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10689 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10690 else if (FAKELIGHT_ENABLED)
10691 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10692 else if (rsurface.uselightmaptexture)
10693 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10695 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10697 case TEXTURELAYERTYPE_TEXTURE:
10698 // singletexture unlit texture with transparency support
10699 R_Mesh_TexBind(0, layer->texture);
10700 R_Mesh_TexMatrix(0, &layer->texmatrix);
10701 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10702 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10703 R_Mesh_TexBind(1, 0);
10704 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10705 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10707 case TEXTURELAYERTYPE_FOG:
10708 // singletexture fogging
10709 if (layer->texture)
10711 R_Mesh_TexBind(0, layer->texture);
10712 R_Mesh_TexMatrix(0, &layer->texmatrix);
10713 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10714 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10718 R_Mesh_TexBind(0, 0);
10719 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10721 R_Mesh_TexBind(1, 0);
10722 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10723 // generate a color array for the fog pass
10724 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10725 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10729 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10732 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10734 GL_DepthFunc(GL_LEQUAL);
10735 GL_AlphaTest(false);
10739 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10741 // OpenGL 1.1 - crusty old voodoo path
10744 const texturelayer_t *layer;
10745 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);
10746 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10748 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10750 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10752 if (layerindex == 0)
10753 GL_AlphaTest(true);
10756 GL_AlphaTest(false);
10757 GL_DepthFunc(GL_EQUAL);
10760 GL_DepthMask(layer->depthmask && writedepth);
10761 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10762 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10763 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10764 switch (layer->type)
10766 case TEXTURELAYERTYPE_LITTEXTURE:
10767 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10769 // two-pass lit texture with 2x rgbscale
10770 // first the lightmap pass
10771 R_Mesh_TexBind(0, r_texture_white);
10772 R_Mesh_TexMatrix(0, NULL);
10773 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10774 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10775 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10776 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10777 else if (FAKELIGHT_ENABLED)
10778 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10779 else if (rsurface.uselightmaptexture)
10780 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10782 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10783 // then apply the texture to it
10784 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10785 R_Mesh_TexBind(0, layer->texture);
10786 R_Mesh_TexMatrix(0, &layer->texmatrix);
10787 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10788 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10789 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);
10793 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10794 R_Mesh_TexBind(0, layer->texture);
10795 R_Mesh_TexMatrix(0, &layer->texmatrix);
10796 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10797 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10798 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10799 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);
10800 else if (FAKELIGHT_ENABLED)
10801 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);
10803 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);
10806 case TEXTURELAYERTYPE_TEXTURE:
10807 // singletexture unlit texture with transparency support
10808 R_Mesh_TexBind(0, layer->texture);
10809 R_Mesh_TexMatrix(0, &layer->texmatrix);
10810 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10811 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10812 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);
10814 case TEXTURELAYERTYPE_FOG:
10815 // singletexture fogging
10816 if (layer->texture)
10818 R_Mesh_TexBind(0, layer->texture);
10819 R_Mesh_TexMatrix(0, &layer->texmatrix);
10820 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10821 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10825 R_Mesh_TexBind(0, 0);
10826 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10828 // generate a color array for the fog pass
10829 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10830 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10834 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10837 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10839 GL_DepthFunc(GL_LEQUAL);
10840 GL_AlphaTest(false);
10844 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10848 r_vertexgeneric_t *batchvertex;
10850 texture_t *t = rsurface.texture;
10852 // R_Mesh_ResetTextureState();
10853 R_SetupShader_Generic_NoTexture(false, false);
10855 if(t && t->currentskinframe)
10857 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10858 c[3] *= t->currentalpha;
10868 if (t->pantstexture || t->shirttexture)
10870 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10871 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10872 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10875 // brighten it up (as texture value 127 means "unlit")
10876 c[0] *= 2 * r_refdef.view.colorscale;
10877 c[1] *= 2 * r_refdef.view.colorscale;
10878 c[2] *= 2 * r_refdef.view.colorscale;
10880 if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10881 c[3] *= r_wateralpha.value;
10883 if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10885 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10886 GL_DepthMask(false);
10888 else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10890 GL_BlendFunc(GL_ONE, GL_ONE);
10891 GL_DepthMask(false);
10893 else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10895 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10896 GL_DepthMask(false);
10898 else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10900 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10901 GL_DepthMask(false);
10905 GL_BlendFunc(GL_ONE, GL_ZERO);
10906 GL_DepthMask(writedepth);
10909 if (r_showsurfaces.integer == 3)
10911 rsurface.passcolor4f = NULL;
10913 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10915 qboolean applycolor = true;
10918 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10920 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10922 else if (FAKELIGHT_ENABLED)
10924 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10926 RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10930 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10932 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10933 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10934 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10935 RSurf_DrawBatch_GL11_ApplyAmbient();
10938 if(!rsurface.passcolor4f)
10939 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10941 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10942 if(r_refdef.fogenabled)
10943 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10944 RSurf_DrawBatch_GL11_ClampColor();
10946 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10947 R_SetupShader_Generic_NoTexture(false, false);
10950 else if (!r_refdef.view.showdebug)
10952 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10953 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10954 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10956 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10957 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10959 R_Mesh_PrepareVertices_Generic_Unlock();
10962 else if (r_showsurfaces.integer == 4)
10964 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10965 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10966 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10968 unsigned char d = (vi << 3) * (1.0f / 256.0f);
10969 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10970 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10972 R_Mesh_PrepareVertices_Generic_Unlock();
10975 else if (r_showsurfaces.integer == 2)
10978 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10979 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10980 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10982 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10983 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10984 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10985 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10986 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10987 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10988 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10990 R_Mesh_PrepareVertices_Generic_Unlock();
10991 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10995 int texturesurfaceindex;
10997 const msurface_t *surface;
10998 float surfacecolor4f[4];
10999 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11000 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11002 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11004 surface = texturesurfacelist[texturesurfaceindex];
11005 k = (int)(((size_t)surface) / sizeof(msurface_t));
11006 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11007 for (j = 0;j < surface->num_vertices;j++)
11009 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11010 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11014 R_Mesh_PrepareVertices_Generic_Unlock();
11019 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11022 RSurf_SetupDepthAndCulling();
11023 if (r_showsurfaces.integer)
11025 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11028 switch (vid.renderpath)
11030 case RENDERPATH_GL20:
11031 case RENDERPATH_D3D9:
11032 case RENDERPATH_D3D10:
11033 case RENDERPATH_D3D11:
11034 case RENDERPATH_SOFT:
11035 case RENDERPATH_GLES2:
11036 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11038 case RENDERPATH_GL13:
11039 case RENDERPATH_GLES1:
11040 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11042 case RENDERPATH_GL11:
11043 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11049 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11052 int texturenumsurfaces, endsurface;
11053 texture_t *texture;
11054 const msurface_t *surface;
11055 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11057 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11058 RSurf_ActiveModelEntity(ent, false, false, false);
11061 switch (vid.renderpath)
11063 case RENDERPATH_GL20:
11064 case RENDERPATH_D3D9:
11065 case RENDERPATH_D3D10:
11066 case RENDERPATH_D3D11:
11067 case RENDERPATH_SOFT:
11068 case RENDERPATH_GLES2:
11069 RSurf_ActiveModelEntity(ent, true, true, false);
11071 case RENDERPATH_GL11:
11072 case RENDERPATH_GL13:
11073 case RENDERPATH_GLES1:
11074 RSurf_ActiveModelEntity(ent, true, false, false);
11079 if (r_transparentdepthmasking.integer)
11081 qboolean setup = false;
11082 for (i = 0;i < numsurfaces;i = j)
11085 surface = rsurface.modelsurfaces + surfacelist[i];
11086 texture = surface->texture;
11087 rsurface.texture = R_GetCurrentTexture(texture);
11088 rsurface.lightmaptexture = NULL;
11089 rsurface.deluxemaptexture = NULL;
11090 rsurface.uselightmaptexture = false;
11091 // scan ahead until we find a different texture
11092 endsurface = min(i + 1024, numsurfaces);
11093 texturenumsurfaces = 0;
11094 texturesurfacelist[texturenumsurfaces++] = surface;
11095 for (;j < endsurface;j++)
11097 surface = rsurface.modelsurfaces + surfacelist[j];
11098 if (texture != surface->texture)
11100 texturesurfacelist[texturenumsurfaces++] = surface;
11102 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11104 // render the range of surfaces as depth
11108 GL_ColorMask(0,0,0,0);
11110 GL_DepthTest(true);
11111 GL_BlendFunc(GL_ONE, GL_ZERO);
11112 GL_DepthMask(true);
11113 // R_Mesh_ResetTextureState();
11115 RSurf_SetupDepthAndCulling();
11116 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11117 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11118 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11122 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11125 for (i = 0;i < numsurfaces;i = j)
11128 surface = rsurface.modelsurfaces + surfacelist[i];
11129 texture = surface->texture;
11130 rsurface.texture = R_GetCurrentTexture(texture);
11131 // scan ahead until we find a different texture
11132 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11133 texturenumsurfaces = 0;
11134 texturesurfacelist[texturenumsurfaces++] = surface;
11135 if(FAKELIGHT_ENABLED)
11137 rsurface.lightmaptexture = NULL;
11138 rsurface.deluxemaptexture = NULL;
11139 rsurface.uselightmaptexture = false;
11140 for (;j < endsurface;j++)
11142 surface = rsurface.modelsurfaces + surfacelist[j];
11143 if (texture != surface->texture)
11145 texturesurfacelist[texturenumsurfaces++] = surface;
11150 rsurface.lightmaptexture = surface->lightmaptexture;
11151 rsurface.deluxemaptexture = surface->deluxemaptexture;
11152 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11153 for (;j < endsurface;j++)
11155 surface = rsurface.modelsurfaces + surfacelist[j];
11156 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11158 texturesurfacelist[texturenumsurfaces++] = surface;
11161 // render the range of surfaces
11162 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11164 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11167 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11169 // transparent surfaces get pushed off into the transparent queue
11170 int surfacelistindex;
11171 const msurface_t *surface;
11172 vec3_t tempcenter, center;
11173 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11175 surface = texturesurfacelist[surfacelistindex];
11176 if (r_transparent_sortsurfacesbynearest.integer)
11178 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11179 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11180 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11184 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11185 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11186 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11188 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11189 if (rsurface.entity->transparent_offset) // transparent offset
11191 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11192 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11193 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11195 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);
11199 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11201 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11203 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11205 RSurf_SetupDepthAndCulling();
11206 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11207 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11208 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11212 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11216 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11219 if (!rsurface.texture->currentnumlayers)
11221 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11222 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11224 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11226 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11227 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11228 else if (!rsurface.texture->currentnumlayers)
11230 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11232 // in the deferred case, transparent surfaces were queued during prepass
11233 if (!r_shadow_usingdeferredprepass)
11234 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11238 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11239 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11244 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11247 texture_t *texture;
11248 R_FrameData_SetMark();
11249 // break the surface list down into batches by texture and use of lightmapping
11250 for (i = 0;i < numsurfaces;i = j)
11253 // texture is the base texture pointer, rsurface.texture is the
11254 // current frame/skin the texture is directing us to use (for example
11255 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11256 // use skin 1 instead)
11257 texture = surfacelist[i]->texture;
11258 rsurface.texture = R_GetCurrentTexture(texture);
11259 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11261 // if this texture is not the kind we want, skip ahead to the next one
11262 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11266 if(FAKELIGHT_ENABLED || depthonly || prepass)
11268 rsurface.lightmaptexture = NULL;
11269 rsurface.deluxemaptexture = NULL;
11270 rsurface.uselightmaptexture = false;
11271 // simply scan ahead until we find a different texture or lightmap state
11272 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11277 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11278 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11279 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11280 // simply scan ahead until we find a different texture or lightmap state
11281 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11284 // render the range of surfaces
11285 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11287 R_FrameData_ReturnToMark();
11290 float locboxvertex3f[6*4*3] =
11292 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11293 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11294 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11295 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11296 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11297 1,0,0, 0,0,0, 0,1,0, 1,1,0
11300 unsigned short locboxelements[6*2*3] =
11305 12,13,14, 12,14,15,
11306 16,17,18, 16,18,19,
11310 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11313 cl_locnode_t *loc = (cl_locnode_t *)ent;
11315 float vertex3f[6*4*3];
11317 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11318 GL_DepthMask(false);
11319 GL_DepthRange(0, 1);
11320 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11321 GL_DepthTest(true);
11322 GL_CullFace(GL_NONE);
11323 R_EntityMatrix(&identitymatrix);
11325 // R_Mesh_ResetTextureState();
11327 i = surfacelist[0];
11328 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11329 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11330 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11331 surfacelist[0] < 0 ? 0.5f : 0.125f);
11333 if (VectorCompare(loc->mins, loc->maxs))
11335 VectorSet(size, 2, 2, 2);
11336 VectorMA(loc->mins, -0.5f, size, mins);
11340 VectorCopy(loc->mins, mins);
11341 VectorSubtract(loc->maxs, loc->mins, size);
11344 for (i = 0;i < 6*4*3;)
11345 for (j = 0;j < 3;j++, i++)
11346 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11348 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11349 R_SetupShader_Generic_NoTexture(false, false);
11350 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11353 void R_DrawLocs(void)
11356 cl_locnode_t *loc, *nearestloc;
11358 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11359 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11361 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11362 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11366 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11368 if (decalsystem->decals)
11369 Mem_Free(decalsystem->decals);
11370 memset(decalsystem, 0, sizeof(*decalsystem));
11373 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)
11376 tridecal_t *decals;
11379 // expand or initialize the system
11380 if (decalsystem->maxdecals <= decalsystem->numdecals)
11382 decalsystem_t old = *decalsystem;
11383 qboolean useshortelements;
11384 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11385 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11386 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)));
11387 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11388 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11389 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11390 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11391 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11392 if (decalsystem->numdecals)
11393 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11395 Mem_Free(old.decals);
11396 for (i = 0;i < decalsystem->maxdecals*3;i++)
11397 decalsystem->element3i[i] = i;
11398 if (useshortelements)
11399 for (i = 0;i < decalsystem->maxdecals*3;i++)
11400 decalsystem->element3s[i] = i;
11403 // grab a decal and search for another free slot for the next one
11404 decals = decalsystem->decals;
11405 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11406 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11408 decalsystem->freedecal = i;
11409 if (decalsystem->numdecals <= i)
11410 decalsystem->numdecals = i + 1;
11412 // initialize the decal
11414 decal->triangleindex = triangleindex;
11415 decal->surfaceindex = surfaceindex;
11416 decal->decalsequence = decalsequence;
11417 decal->color4f[0][0] = c0[0];
11418 decal->color4f[0][1] = c0[1];
11419 decal->color4f[0][2] = c0[2];
11420 decal->color4f[0][3] = 1;
11421 decal->color4f[1][0] = c1[0];
11422 decal->color4f[1][1] = c1[1];
11423 decal->color4f[1][2] = c1[2];
11424 decal->color4f[1][3] = 1;
11425 decal->color4f[2][0] = c2[0];
11426 decal->color4f[2][1] = c2[1];
11427 decal->color4f[2][2] = c2[2];
11428 decal->color4f[2][3] = 1;
11429 decal->vertex3f[0][0] = v0[0];
11430 decal->vertex3f[0][1] = v0[1];
11431 decal->vertex3f[0][2] = v0[2];
11432 decal->vertex3f[1][0] = v1[0];
11433 decal->vertex3f[1][1] = v1[1];
11434 decal->vertex3f[1][2] = v1[2];
11435 decal->vertex3f[2][0] = v2[0];
11436 decal->vertex3f[2][1] = v2[1];
11437 decal->vertex3f[2][2] = v2[2];
11438 decal->texcoord2f[0][0] = t0[0];
11439 decal->texcoord2f[0][1] = t0[1];
11440 decal->texcoord2f[1][0] = t1[0];
11441 decal->texcoord2f[1][1] = t1[1];
11442 decal->texcoord2f[2][0] = t2[0];
11443 decal->texcoord2f[2][1] = t2[1];
11444 TriangleNormal(v0, v1, v2, decal->plane);
11445 VectorNormalize(decal->plane);
11446 decal->plane[3] = DotProduct(v0, decal->plane);
11449 extern cvar_t cl_decals_bias;
11450 extern cvar_t cl_decals_models;
11451 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11452 // baseparms, parms, temps
11453 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)
11458 const float *vertex3f;
11459 const float *normal3f;
11461 float points[2][9][3];
11468 e = rsurface.modelelement3i + 3*triangleindex;
11470 vertex3f = rsurface.modelvertex3f;
11471 normal3f = rsurface.modelnormal3f;
11475 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11477 index = 3*e[cornerindex];
11478 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11483 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11485 index = 3*e[cornerindex];
11486 VectorCopy(vertex3f + index, v[cornerindex]);
11491 //TriangleNormal(v[0], v[1], v[2], normal);
11492 //if (DotProduct(normal, localnormal) < 0.0f)
11494 // clip by each of the box planes formed from the projection matrix
11495 // if anything survives, we emit the decal
11496 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]);
11499 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]);
11502 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]);
11505 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]);
11508 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]);
11511 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]);
11514 // some part of the triangle survived, so we have to accept it...
11517 // dynamic always uses the original triangle
11519 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11521 index = 3*e[cornerindex];
11522 VectorCopy(vertex3f + index, v[cornerindex]);
11525 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11527 // convert vertex positions to texcoords
11528 Matrix4x4_Transform(projection, v[cornerindex], temp);
11529 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11530 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11531 // calculate distance fade from the projection origin
11532 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11533 f = bound(0.0f, f, 1.0f);
11534 c[cornerindex][0] = r * f;
11535 c[cornerindex][1] = g * f;
11536 c[cornerindex][2] = b * f;
11537 c[cornerindex][3] = 1.0f;
11538 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11541 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);
11543 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11544 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);
11546 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)
11548 matrix4x4_t projection;
11549 decalsystem_t *decalsystem;
11552 const msurface_t *surface;
11553 const msurface_t *surfaces;
11554 const int *surfacelist;
11555 const texture_t *texture;
11557 int numsurfacelist;
11558 int surfacelistindex;
11561 float localorigin[3];
11562 float localnormal[3];
11563 float localmins[3];
11564 float localmaxs[3];
11567 float planes[6][4];
11570 int bih_triangles_count;
11571 int bih_triangles[256];
11572 int bih_surfaces[256];
11574 decalsystem = &ent->decalsystem;
11575 model = ent->model;
11576 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11578 R_DecalSystem_Reset(&ent->decalsystem);
11582 if (!model->brush.data_leafs && !cl_decals_models.integer)
11584 if (decalsystem->model)
11585 R_DecalSystem_Reset(decalsystem);
11589 if (decalsystem->model != model)
11590 R_DecalSystem_Reset(decalsystem);
11591 decalsystem->model = model;
11593 RSurf_ActiveModelEntity(ent, true, false, false);
11595 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11596 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11597 VectorNormalize(localnormal);
11598 localsize = worldsize*rsurface.inversematrixscale;
11599 localmins[0] = localorigin[0] - localsize;
11600 localmins[1] = localorigin[1] - localsize;
11601 localmins[2] = localorigin[2] - localsize;
11602 localmaxs[0] = localorigin[0] + localsize;
11603 localmaxs[1] = localorigin[1] + localsize;
11604 localmaxs[2] = localorigin[2] + localsize;
11606 //VectorCopy(localnormal, planes[4]);
11607 //VectorVectors(planes[4], planes[2], planes[0]);
11608 AnglesFromVectors(angles, localnormal, NULL, false);
11609 AngleVectors(angles, planes[0], planes[2], planes[4]);
11610 VectorNegate(planes[0], planes[1]);
11611 VectorNegate(planes[2], planes[3]);
11612 VectorNegate(planes[4], planes[5]);
11613 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11614 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11615 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11616 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11617 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11618 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11623 matrix4x4_t forwardprojection;
11624 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11625 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11630 float projectionvector[4][3];
11631 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11632 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11633 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11634 projectionvector[0][0] = planes[0][0] * ilocalsize;
11635 projectionvector[0][1] = planes[1][0] * ilocalsize;
11636 projectionvector[0][2] = planes[2][0] * ilocalsize;
11637 projectionvector[1][0] = planes[0][1] * ilocalsize;
11638 projectionvector[1][1] = planes[1][1] * ilocalsize;
11639 projectionvector[1][2] = planes[2][1] * ilocalsize;
11640 projectionvector[2][0] = planes[0][2] * ilocalsize;
11641 projectionvector[2][1] = planes[1][2] * ilocalsize;
11642 projectionvector[2][2] = planes[2][2] * ilocalsize;
11643 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11644 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11645 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11646 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11650 dynamic = model->surfmesh.isanimated;
11651 numsurfacelist = model->nummodelsurfaces;
11652 surfacelist = model->sortedmodelsurfaces;
11653 surfaces = model->data_surfaces;
11656 bih_triangles_count = -1;
11659 if(model->render_bih.numleafs)
11660 bih = &model->render_bih;
11661 else if(model->collision_bih.numleafs)
11662 bih = &model->collision_bih;
11665 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11666 if(bih_triangles_count == 0)
11668 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11670 if(bih_triangles_count > 0)
11672 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11674 surfaceindex = bih_surfaces[triangleindex];
11675 surface = surfaces + surfaceindex;
11676 texture = surface->texture;
11677 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11679 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11681 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11686 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11688 surfaceindex = surfacelist[surfacelistindex];
11689 surface = surfaces + surfaceindex;
11690 // check cull box first because it rejects more than any other check
11691 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11693 // skip transparent surfaces
11694 texture = surface->texture;
11695 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11697 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11699 numtriangles = surface->num_triangles;
11700 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11701 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11706 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11707 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)
11709 int renderentityindex;
11710 float worldmins[3];
11711 float worldmaxs[3];
11712 entity_render_t *ent;
11714 if (!cl_decals_newsystem.integer)
11717 worldmins[0] = worldorigin[0] - worldsize;
11718 worldmins[1] = worldorigin[1] - worldsize;
11719 worldmins[2] = worldorigin[2] - worldsize;
11720 worldmaxs[0] = worldorigin[0] + worldsize;
11721 worldmaxs[1] = worldorigin[1] + worldsize;
11722 worldmaxs[2] = worldorigin[2] + worldsize;
11724 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11726 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11728 ent = r_refdef.scene.entities[renderentityindex];
11729 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11732 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11736 typedef struct r_decalsystem_splatqueue_s
11738 vec3_t worldorigin;
11739 vec3_t worldnormal;
11743 unsigned int decalsequence;
11745 r_decalsystem_splatqueue_t;
11747 int r_decalsystem_numqueued = 0;
11748 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11750 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)
11752 r_decalsystem_splatqueue_t *queue;
11754 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11757 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11758 VectorCopy(worldorigin, queue->worldorigin);
11759 VectorCopy(worldnormal, queue->worldnormal);
11760 Vector4Set(queue->color, r, g, b, a);
11761 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11762 queue->worldsize = worldsize;
11763 queue->decalsequence = cl.decalsequence++;
11766 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11769 r_decalsystem_splatqueue_t *queue;
11771 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11772 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);
11773 r_decalsystem_numqueued = 0;
11776 extern cvar_t cl_decals_max;
11777 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11780 decalsystem_t *decalsystem = &ent->decalsystem;
11782 unsigned int killsequence;
11787 if (!decalsystem->numdecals)
11790 if (r_showsurfaces.integer)
11793 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11795 R_DecalSystem_Reset(decalsystem);
11799 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11800 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11802 if (decalsystem->lastupdatetime)
11803 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11806 decalsystem->lastupdatetime = r_refdef.scene.time;
11807 numdecals = decalsystem->numdecals;
11809 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11811 if (decal->color4f[0][3])
11813 decal->lived += frametime;
11814 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11816 memset(decal, 0, sizeof(*decal));
11817 if (decalsystem->freedecal > i)
11818 decalsystem->freedecal = i;
11822 decal = decalsystem->decals;
11823 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11826 // collapse the array by shuffling the tail decals into the gaps
11829 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11830 decalsystem->freedecal++;
11831 if (decalsystem->freedecal == numdecals)
11833 decal[decalsystem->freedecal] = decal[--numdecals];
11836 decalsystem->numdecals = numdecals;
11838 if (numdecals <= 0)
11840 // if there are no decals left, reset decalsystem
11841 R_DecalSystem_Reset(decalsystem);
11845 extern skinframe_t *decalskinframe;
11846 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11849 decalsystem_t *decalsystem = &ent->decalsystem;
11858 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11861 numdecals = decalsystem->numdecals;
11865 if (r_showsurfaces.integer)
11868 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11870 R_DecalSystem_Reset(decalsystem);
11874 // if the model is static it doesn't matter what value we give for
11875 // wantnormals and wanttangents, so this logic uses only rules applicable
11876 // to a model, knowing that they are meaningless otherwise
11877 RSurf_ActiveModelEntity(ent, false, false, false);
11879 decalsystem->lastupdatetime = r_refdef.scene.time;
11881 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11883 // update vertex positions for animated models
11884 v3f = decalsystem->vertex3f;
11885 c4f = decalsystem->color4f;
11886 t2f = decalsystem->texcoord2f;
11887 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11889 if (!decal->color4f[0][3])
11892 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11896 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11899 // update color values for fading decals
11900 if (decal->lived >= cl_decals_time.value)
11901 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11905 c4f[ 0] = decal->color4f[0][0] * alpha;
11906 c4f[ 1] = decal->color4f[0][1] * alpha;
11907 c4f[ 2] = decal->color4f[0][2] * alpha;
11909 c4f[ 4] = decal->color4f[1][0] * alpha;
11910 c4f[ 5] = decal->color4f[1][1] * alpha;
11911 c4f[ 6] = decal->color4f[1][2] * alpha;
11913 c4f[ 8] = decal->color4f[2][0] * alpha;
11914 c4f[ 9] = decal->color4f[2][1] * alpha;
11915 c4f[10] = decal->color4f[2][2] * alpha;
11918 t2f[0] = decal->texcoord2f[0][0];
11919 t2f[1] = decal->texcoord2f[0][1];
11920 t2f[2] = decal->texcoord2f[1][0];
11921 t2f[3] = decal->texcoord2f[1][1];
11922 t2f[4] = decal->texcoord2f[2][0];
11923 t2f[5] = decal->texcoord2f[2][1];
11925 // update vertex positions for animated models
11926 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11928 e = rsurface.modelelement3i + 3*decal->triangleindex;
11929 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11930 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11931 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11935 VectorCopy(decal->vertex3f[0], v3f);
11936 VectorCopy(decal->vertex3f[1], v3f + 3);
11937 VectorCopy(decal->vertex3f[2], v3f + 6);
11940 if (r_refdef.fogenabled)
11942 alpha = RSurf_FogVertex(v3f);
11943 VectorScale(c4f, alpha, c4f);
11944 alpha = RSurf_FogVertex(v3f + 3);
11945 VectorScale(c4f + 4, alpha, c4f + 4);
11946 alpha = RSurf_FogVertex(v3f + 6);
11947 VectorScale(c4f + 8, alpha, c4f + 8);
11958 r_refdef.stats[r_stat_drawndecals] += numtris;
11960 // now render the decals all at once
11961 // (this assumes they all use one particle font texture!)
11962 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);
11963 // R_Mesh_ResetTextureState();
11964 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11965 GL_DepthMask(false);
11966 GL_DepthRange(0, 1);
11967 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11968 GL_DepthTest(true);
11969 GL_CullFace(GL_NONE);
11970 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11971 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11972 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11976 static void R_DrawModelDecals(void)
11980 // fade faster when there are too many decals
11981 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11982 for (i = 0;i < r_refdef.scene.numentities;i++)
11983 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11985 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11986 for (i = 0;i < r_refdef.scene.numentities;i++)
11987 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11988 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11990 R_DecalSystem_ApplySplatEntitiesQueue();
11992 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11993 for (i = 0;i < r_refdef.scene.numentities;i++)
11994 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11996 r_refdef.stats[r_stat_totaldecals] += numdecals;
11998 if (r_showsurfaces.integer)
12001 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12003 for (i = 0;i < r_refdef.scene.numentities;i++)
12005 if (!r_refdef.viewcache.entityvisible[i])
12007 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12008 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12012 extern cvar_t mod_collision_bih;
12013 static void R_DrawDebugModel(void)
12015 entity_render_t *ent = rsurface.entity;
12016 int i, j, flagsmask;
12017 const msurface_t *surface;
12018 dp_model_t *model = ent->model;
12020 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12023 if (r_showoverdraw.value > 0)
12025 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12026 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12027 R_SetupShader_Generic_NoTexture(false, false);
12028 GL_DepthTest(false);
12029 GL_DepthMask(false);
12030 GL_DepthRange(0, 1);
12031 GL_BlendFunc(GL_ONE, GL_ONE);
12032 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12034 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12036 rsurface.texture = R_GetCurrentTexture(surface->texture);
12037 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12039 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12040 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12041 if (!rsurface.texture->currentlayers->depthmask)
12042 GL_Color(c, 0, 0, 1.0f);
12043 else if (ent == r_refdef.scene.worldentity)
12044 GL_Color(c, c, c, 1.0f);
12046 GL_Color(0, c, 0, 1.0f);
12047 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12051 rsurface.texture = NULL;
12054 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12056 // R_Mesh_ResetTextureState();
12057 R_SetupShader_Generic_NoTexture(false, false);
12058 GL_DepthRange(0, 1);
12059 GL_DepthTest(!r_showdisabledepthtest.integer);
12060 GL_DepthMask(false);
12061 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12063 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12067 qboolean cullbox = false;
12068 const q3mbrush_t *brush;
12069 const bih_t *bih = &model->collision_bih;
12070 const bih_leaf_t *bihleaf;
12071 float vertex3f[3][3];
12072 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12073 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12075 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12077 switch (bihleaf->type)
12080 brush = model->brush.data_brushes + bihleaf->itemindex;
12081 if (brush->colbrushf && brush->colbrushf->numtriangles)
12083 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);
12084 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12085 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12088 case BIH_COLLISIONTRIANGLE:
12089 triangleindex = bihleaf->itemindex;
12090 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12091 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12092 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12093 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);
12094 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12095 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12097 case BIH_RENDERTRIANGLE:
12098 triangleindex = bihleaf->itemindex;
12099 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12100 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12101 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12102 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);
12103 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12104 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12110 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12113 if (r_showtris.integer && qglPolygonMode)
12115 if (r_showdisabledepthtest.integer)
12117 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12118 GL_DepthMask(false);
12122 GL_BlendFunc(GL_ONE, GL_ZERO);
12123 GL_DepthMask(true);
12125 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12126 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12128 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12130 rsurface.texture = R_GetCurrentTexture(surface->texture);
12131 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12133 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12134 if (!rsurface.texture->currentlayers->depthmask)
12135 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12136 else if (ent == r_refdef.scene.worldentity)
12137 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12139 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12140 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12144 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12145 rsurface.texture = NULL;
12148 if (r_shownormals.value != 0 && qglBegin)
12152 if (r_showdisabledepthtest.integer)
12154 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12155 GL_DepthMask(false);
12159 GL_BlendFunc(GL_ONE, GL_ZERO);
12160 GL_DepthMask(true);
12162 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12164 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12166 rsurface.texture = R_GetCurrentTexture(surface->texture);
12167 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12169 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12170 qglBegin(GL_LINES);
12171 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12173 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12175 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12176 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12177 qglVertex3f(v[0], v[1], v[2]);
12178 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12179 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12180 qglVertex3f(v[0], v[1], v[2]);
12183 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12185 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12187 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12188 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12189 qglVertex3f(v[0], v[1], v[2]);
12190 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12191 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12192 qglVertex3f(v[0], v[1], v[2]);
12195 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12197 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12199 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12200 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12201 qglVertex3f(v[0], v[1], v[2]);
12202 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12203 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12204 qglVertex3f(v[0], v[1], v[2]);
12207 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12209 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12211 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12212 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12213 qglVertex3f(v[0], v[1], v[2]);
12214 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12215 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12216 qglVertex3f(v[0], v[1], v[2]);
12223 rsurface.texture = NULL;
12228 int r_maxsurfacelist = 0;
12229 const msurface_t **r_surfacelist = NULL;
12230 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12232 int i, j, endj, flagsmask;
12233 dp_model_t *model = ent->model;
12234 msurface_t *surfaces;
12235 unsigned char *update;
12236 int numsurfacelist = 0;
12240 if (r_maxsurfacelist < model->num_surfaces)
12242 r_maxsurfacelist = model->num_surfaces;
12244 Mem_Free((msurface_t **)r_surfacelist);
12245 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12248 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12249 RSurf_ActiveModelEntity(ent, false, false, false);
12251 RSurf_ActiveModelEntity(ent, true, true, true);
12252 else if (depthonly)
12254 switch (vid.renderpath)
12256 case RENDERPATH_GL20:
12257 case RENDERPATH_D3D9:
12258 case RENDERPATH_D3D10:
12259 case RENDERPATH_D3D11:
12260 case RENDERPATH_SOFT:
12261 case RENDERPATH_GLES2:
12262 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12264 case RENDERPATH_GL11:
12265 case RENDERPATH_GL13:
12266 case RENDERPATH_GLES1:
12267 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12273 switch (vid.renderpath)
12275 case RENDERPATH_GL20:
12276 case RENDERPATH_D3D9:
12277 case RENDERPATH_D3D10:
12278 case RENDERPATH_D3D11:
12279 case RENDERPATH_SOFT:
12280 case RENDERPATH_GLES2:
12281 RSurf_ActiveModelEntity(ent, true, true, false);
12283 case RENDERPATH_GL11:
12284 case RENDERPATH_GL13:
12285 case RENDERPATH_GLES1:
12286 RSurf_ActiveModelEntity(ent, true, false, false);
12291 surfaces = model->data_surfaces;
12292 update = model->brushq1.lightmapupdateflags;
12294 // update light styles
12295 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12297 model_brush_lightstyleinfo_t *style;
12298 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12300 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12302 int *list = style->surfacelist;
12303 style->value = r_refdef.scene.lightstylevalue[style->style];
12304 for (j = 0;j < style->numsurfaces;j++)
12305 update[list[j]] = true;
12310 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12314 R_DrawDebugModel();
12315 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12319 rsurface.lightmaptexture = NULL;
12320 rsurface.deluxemaptexture = NULL;
12321 rsurface.uselightmaptexture = false;
12322 rsurface.texture = NULL;
12323 rsurface.rtlight = NULL;
12324 numsurfacelist = 0;
12325 // add visible surfaces to draw list
12326 if (ent == r_refdef.scene.worldentity)
12328 // for the world entity, check surfacevisible
12329 for (i = 0;i < model->nummodelsurfaces;i++)
12331 j = model->sortedmodelsurfaces[i];
12332 if (r_refdef.viewcache.world_surfacevisible[j])
12333 r_surfacelist[numsurfacelist++] = surfaces + j;
12338 // add all surfaces
12339 for (i = 0; i < model->nummodelsurfaces; i++)
12340 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12342 // don't do anything if there were no surfaces
12343 if (!numsurfacelist)
12345 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12348 // update lightmaps if needed
12352 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12357 R_BuildLightMap(ent, surfaces + j);
12362 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12364 // add to stats if desired
12365 if (r_speeds.integer && !skysurfaces && !depthonly)
12367 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12368 for (j = 0;j < numsurfacelist;j++)
12369 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12372 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12375 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12378 static texture_t texture;
12379 static msurface_t surface;
12380 const msurface_t *surfacelist = &surface;
12382 // fake enough texture and surface state to render this geometry
12384 texture.update_lastrenderframe = -1; // regenerate this texture
12385 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12386 texture.basealpha = 1.0f;
12387 texture.currentskinframe = skinframe;
12388 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12389 texture.offsetmapping = OFFSETMAPPING_OFF;
12390 texture.offsetscale = 1;
12391 texture.specularscalemod = 1;
12392 texture.specularpowermod = 1;
12393 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12394 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12395 // JUST GREP FOR "specularscalemod = 1".
12397 for (q = 0; q < 3; q++)
12399 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12400 texture.render_modellight_lightdir[q] = q == 2;
12401 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12402 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12403 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12404 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12405 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12406 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12407 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12408 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12410 texture.currentalpha = 1.0f;
12412 surface.texture = &texture;
12413 surface.num_triangles = numtriangles;
12414 surface.num_firsttriangle = firsttriangle;
12415 surface.num_vertices = numvertices;
12416 surface.num_firstvertex = firstvertex;
12419 rsurface.texture = R_GetCurrentTexture(surface.texture);
12420 rsurface.lightmaptexture = NULL;
12421 rsurface.deluxemaptexture = NULL;
12422 rsurface.uselightmaptexture = false;
12423 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12426 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)
12428 static msurface_t surface;
12429 const msurface_t *surfacelist = &surface;
12431 // fake enough texture and surface state to render this geometry
12432 surface.texture = texture;
12433 surface.num_triangles = numtriangles;
12434 surface.num_firsttriangle = firsttriangle;
12435 surface.num_vertices = numvertices;
12436 surface.num_firstvertex = firstvertex;
12439 rsurface.texture = R_GetCurrentTexture(surface.texture);
12440 rsurface.lightmaptexture = NULL;
12441 rsurface.deluxemaptexture = NULL;
12442 rsurface.uselightmaptexture = false;
12443 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);