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"};
81 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
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)"};
83 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
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"};
125 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
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", "1", "increases shadowmap quality (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 vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, 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 static float dummy_colormod[3] = {1, 1, 1};
2226 float *colormod = rsurface.colormod;
2228 matrix4x4_t tempmatrix;
2229 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2230 if (r_trippy.integer && !notrippy)
2231 permutation |= SHADERPERMUTATION_TRIPPY;
2232 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2233 permutation |= SHADERPERMUTATION_ALPHAKILL;
2234 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2235 permutation |= SHADERPERMUTATION_OCCLUDE;
2236 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2237 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2238 if (rsurfacepass == RSURFPASS_BACKGROUND)
2240 // distorted background
2241 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2243 mode = SHADERMODE_WATER;
2244 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2245 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2246 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2248 // this is the right thing to do for wateralpha
2249 GL_BlendFunc(GL_ONE, GL_ZERO);
2250 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2254 // this is the right thing to do for entity alpha
2255 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2259 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2261 mode = SHADERMODE_REFRACTION;
2262 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2263 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2264 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2265 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2269 mode = SHADERMODE_GENERIC;
2270 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2271 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2272 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2274 if (vid.allowalphatocoverage)
2275 GL_AlphaToCoverage(false);
2277 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2279 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2281 switch(rsurface.texture->offsetmapping)
2283 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286 case OFFSETMAPPING_OFF: break;
2289 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291 // normalmap (deferred prepass), may use alpha test on diffuse
2292 mode = SHADERMODE_DEFERREDGEOMETRY;
2293 GL_BlendFunc(GL_ONE, GL_ZERO);
2294 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2295 if (vid.allowalphatocoverage)
2296 GL_AlphaToCoverage(false);
2298 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2300 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2302 switch(rsurface.texture->offsetmapping)
2304 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2305 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2307 case OFFSETMAPPING_OFF: break;
2310 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2311 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2312 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2313 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2315 mode = SHADERMODE_LIGHTSOURCE;
2316 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2317 permutation |= SHADERPERMUTATION_CUBEFILTER;
2318 if (diffusescale > 0)
2319 permutation |= SHADERPERMUTATION_DIFFUSE;
2320 if (specularscale > 0)
2321 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2322 if (r_refdef.fogenabled)
2323 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2324 if (rsurface.texture->colormapping)
2325 permutation |= SHADERPERMUTATION_COLORMAPPING;
2326 if (r_shadow_usingshadowmap2d)
2328 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2329 if(r_shadow_shadowmapvsdct)
2330 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2332 if (r_shadow_shadowmap2ddepthbuffer)
2333 permutation |= SHADERPERMUTATION_DEPTHRGB;
2335 if (rsurface.texture->reflectmasktexture)
2336 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2337 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2338 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2339 if (vid.allowalphatocoverage)
2340 GL_AlphaToCoverage(false);
2342 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2344 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2346 switch(rsurface.texture->offsetmapping)
2348 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2349 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351 case OFFSETMAPPING_OFF: break;
2354 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2355 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2356 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2357 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2358 // unshaded geometry (fullbright or ambient model lighting)
2359 mode = SHADERMODE_FLATCOLOR;
2360 ambientscale = diffusescale = specularscale = 0;
2361 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2362 permutation |= SHADERPERMUTATION_GLOW;
2363 if (r_refdef.fogenabled)
2364 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365 if (rsurface.texture->colormapping)
2366 permutation |= SHADERPERMUTATION_COLORMAPPING;
2367 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2369 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2372 if (r_shadow_shadowmap2ddepthbuffer)
2373 permutation |= SHADERPERMUTATION_DEPTHRGB;
2375 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376 permutation |= SHADERPERMUTATION_REFLECTION;
2377 if (rsurface.texture->reflectmasktexture)
2378 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2379 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2380 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2381 // when using alphatocoverage, we don't need alphakill
2382 if (vid.allowalphatocoverage)
2384 if (r_transparent_alphatocoverage.integer)
2386 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2387 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2390 GL_AlphaToCoverage(false);
2393 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2395 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2397 switch(rsurface.texture->offsetmapping)
2399 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2400 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2401 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2402 case OFFSETMAPPING_OFF: break;
2405 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2406 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2407 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2408 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2409 // directional model lighting
2410 mode = SHADERMODE_LIGHTDIRECTION;
2411 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2412 permutation |= SHADERPERMUTATION_GLOW;
2413 permutation |= SHADERPERMUTATION_DIFFUSE;
2414 if (specularscale > 0)
2415 permutation |= SHADERPERMUTATION_SPECULAR;
2416 if (r_refdef.fogenabled)
2417 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2418 if (rsurface.texture->colormapping)
2419 permutation |= SHADERPERMUTATION_COLORMAPPING;
2420 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2422 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2423 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2425 if (r_shadow_shadowmap2ddepthbuffer)
2426 permutation |= SHADERPERMUTATION_DEPTHRGB;
2428 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2429 permutation |= SHADERPERMUTATION_REFLECTION;
2430 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2431 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2432 if (rsurface.texture->reflectmasktexture)
2433 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2434 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2436 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2437 if (r_shadow_bouncegrid_state.directional)
2438 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2440 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2441 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2442 // when using alphatocoverage, we don't need alphakill
2443 if (vid.allowalphatocoverage)
2445 if (r_transparent_alphatocoverage.integer)
2447 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2448 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2451 GL_AlphaToCoverage(false);
2454 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2456 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2458 switch(rsurface.texture->offsetmapping)
2460 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2461 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2462 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2463 case OFFSETMAPPING_OFF: break;
2466 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2467 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2468 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2469 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2470 // ambient model lighting
2471 mode = SHADERMODE_LIGHTDIRECTION;
2472 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2473 permutation |= SHADERPERMUTATION_GLOW;
2474 if (r_refdef.fogenabled)
2475 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2476 if (rsurface.texture->colormapping)
2477 permutation |= SHADERPERMUTATION_COLORMAPPING;
2478 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2480 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2481 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2483 if (r_shadow_shadowmap2ddepthbuffer)
2484 permutation |= SHADERPERMUTATION_DEPTHRGB;
2486 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2487 permutation |= SHADERPERMUTATION_REFLECTION;
2488 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2489 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2490 if (rsurface.texture->reflectmasktexture)
2491 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2492 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2494 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2495 if (r_shadow_bouncegrid_state.directional)
2496 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2498 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2499 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2500 // when using alphatocoverage, we don't need alphakill
2501 if (vid.allowalphatocoverage)
2503 if (r_transparent_alphatocoverage.integer)
2505 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2506 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2509 GL_AlphaToCoverage(false);
2514 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2516 switch(rsurface.texture->offsetmapping)
2518 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2519 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2520 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2521 case OFFSETMAPPING_OFF: break;
2524 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2525 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2526 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2527 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2529 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2530 permutation |= SHADERPERMUTATION_GLOW;
2531 if (r_refdef.fogenabled)
2532 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2533 if (rsurface.texture->colormapping)
2534 permutation |= SHADERPERMUTATION_COLORMAPPING;
2535 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2537 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2538 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2540 if (r_shadow_shadowmap2ddepthbuffer)
2541 permutation |= SHADERPERMUTATION_DEPTHRGB;
2543 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2544 permutation |= SHADERPERMUTATION_REFLECTION;
2545 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2546 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2547 if (rsurface.texture->reflectmasktexture)
2548 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2549 if (FAKELIGHT_ENABLED)
2551 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2552 mode = SHADERMODE_FAKELIGHT;
2553 permutation |= SHADERPERMUTATION_DIFFUSE;
2554 if (specularscale > 0)
2555 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2557 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2559 // deluxemapping (light direction texture)
2560 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2561 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2563 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2564 permutation |= SHADERPERMUTATION_DIFFUSE;
2565 if (specularscale > 0)
2566 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2568 else if (r_glsl_deluxemapping.integer >= 2)
2570 // fake deluxemapping (uniform light direction in tangentspace)
2571 if (rsurface.uselightmaptexture)
2572 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2574 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2575 permutation |= SHADERPERMUTATION_DIFFUSE;
2576 if (specularscale > 0)
2577 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2579 else if (rsurface.uselightmaptexture)
2581 // ordinary lightmapping (q1bsp, q3bsp)
2582 mode = SHADERMODE_LIGHTMAP;
2586 // ordinary vertex coloring (q3bsp)
2587 mode = SHADERMODE_VERTEXCOLOR;
2589 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2591 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2592 if (r_shadow_bouncegrid_state.directional)
2593 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2595 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2596 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2597 // when using alphatocoverage, we don't need alphakill
2598 if (vid.allowalphatocoverage)
2600 if (r_transparent_alphatocoverage.integer)
2602 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2603 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2606 GL_AlphaToCoverage(false);
2609 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2610 colormod = dummy_colormod;
2611 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2612 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2613 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2614 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2615 switch(vid.renderpath)
2617 case RENDERPATH_D3D9:
2619 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);
2620 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2621 R_SetupShader_SetPermutationHLSL(mode, permutation);
2622 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2623 if (mode == SHADERMODE_LIGHTSOURCE)
2625 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2626 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2630 if (mode == SHADERMODE_LIGHTDIRECTION)
2632 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2635 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2636 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2637 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2638 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2639 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2641 if (mode == SHADERMODE_LIGHTSOURCE)
2643 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2644 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2645 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2646 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2647 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2649 // additive passes are only darkened by fog, not tinted
2650 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2651 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2655 if (mode == SHADERMODE_FLATCOLOR)
2657 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2659 else if (mode == SHADERMODE_LIGHTDIRECTION)
2661 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2662 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2663 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2664 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2665 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2666 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2667 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2671 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2672 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2673 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2674 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2675 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2677 // additive passes are only darkened by fog, not tinted
2678 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2679 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2681 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2682 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2683 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2684 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2685 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2686 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2687 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2688 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2689 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2690 if (mode == SHADERMODE_WATER)
2691 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2693 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2695 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2696 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2700 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2701 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2703 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2704 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2705 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2706 if (rsurface.texture->pantstexture)
2707 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2709 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2710 if (rsurface.texture->shirttexture)
2711 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2713 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2714 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2715 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2716 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2717 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2718 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2719 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2720 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2721 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2722 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2724 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2725 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2726 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2727 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2729 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2730 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2731 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2732 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2733 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2734 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2735 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2736 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2737 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2738 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2739 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2740 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2741 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2742 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2743 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2744 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2745 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2746 if (rsurfacepass == RSURFPASS_BACKGROUND)
2748 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2749 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2750 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2754 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2756 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2757 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2758 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2759 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2761 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2762 if (rsurface.rtlight)
2764 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2765 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2770 case RENDERPATH_D3D10:
2771 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2773 case RENDERPATH_D3D11:
2774 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2776 case RENDERPATH_GL20:
2777 case RENDERPATH_GLES2:
2778 if (!vid.useinterleavedarrays)
2780 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);
2781 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2782 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2783 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2784 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2785 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2786 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2787 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2788 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2789 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2790 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2794 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);
2795 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2797 // this has to be after RSurf_PrepareVerticesForBatch
2798 if (rsurface.batchskeletaltransform3x4buffer)
2799 permutation |= SHADERPERMUTATION_SKELETAL;
2800 R_SetupShader_SetPermutationGLSL(mode, permutation);
2801 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2802 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);
2804 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2805 if (mode == SHADERMODE_LIGHTSOURCE)
2807 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2808 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2809 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2810 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2811 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2812 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2814 // additive passes are only darkened by fog, not tinted
2815 if (r_glsl_permutation->loc_FogColor >= 0)
2816 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2817 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2821 if (mode == SHADERMODE_FLATCOLOR)
2823 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2825 else if (mode == SHADERMODE_LIGHTDIRECTION)
2827 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2828 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2829 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2830 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2831 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2832 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2833 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2837 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2838 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2839 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2840 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2841 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2843 // additive passes are only darkened by fog, not tinted
2844 if (r_glsl_permutation->loc_FogColor >= 0)
2846 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2847 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2849 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2851 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2852 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]);
2853 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]);
2854 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2855 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2856 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2857 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2858 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2859 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2861 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2862 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2863 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2864 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2866 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]);
2867 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]);
2871 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]);
2872 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]);
2875 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2876 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2877 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2878 if (r_glsl_permutation->loc_Color_Pants >= 0)
2880 if (rsurface.texture->pantstexture)
2881 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2883 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2885 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2887 if (rsurface.texture->shirttexture)
2888 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2890 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2892 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]);
2893 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2894 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2895 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2896 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2897 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2898 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2899 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2900 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2902 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);
2903 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2904 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]);
2905 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2906 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);}
2907 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2909 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2910 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2911 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2912 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2913 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2914 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2915 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2916 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2917 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2918 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2919 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2920 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2921 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2922 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2923 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2924 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2925 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2926 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2927 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2928 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2929 if (rsurfacepass == RSURFPASS_BACKGROUND)
2931 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);
2932 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);
2933 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);
2937 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);
2939 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2940 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2941 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2942 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2944 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2945 if (rsurface.rtlight)
2947 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2948 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2951 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2954 case RENDERPATH_GL11:
2955 case RENDERPATH_GL13:
2956 case RENDERPATH_GLES1:
2958 case RENDERPATH_SOFT:
2959 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);
2960 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2961 R_SetupShader_SetPermutationSoft(mode, permutation);
2962 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2963 if (mode == SHADERMODE_LIGHTSOURCE)
2965 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2966 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2967 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2968 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2969 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2970 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2972 // additive passes are only darkened by fog, not tinted
2973 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2974 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2978 if (mode == SHADERMODE_FLATCOLOR)
2980 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2982 else if (mode == SHADERMODE_LIGHTDIRECTION)
2984 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2985 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2986 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2987 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2988 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2989 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2990 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2994 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2995 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2996 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2997 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2998 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
3000 // additive passes are only darkened by fog, not tinted
3001 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
3002 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
3004 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
3005 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
3006 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]);
3007 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]);
3008 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3009 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
3010 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
3011 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
3012 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3013 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
3015 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
3016 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
3017 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
3018 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
3020 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]);
3021 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]);
3025 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]);
3026 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]);
3029 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
3030 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
3031 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
3032 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
3034 if (rsurface.texture->pantstexture)
3035 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
3037 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
3039 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3041 if (rsurface.texture->shirttexture)
3042 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3044 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3046 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3047 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3048 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3049 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3050 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3051 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3052 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3053 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3054 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3056 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3057 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3058 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3059 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3061 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
3062 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
3063 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
3064 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
3065 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
3066 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
3067 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
3068 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
3069 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
3070 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
3071 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
3072 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3073 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
3074 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
3075 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3076 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3077 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3078 if (rsurfacepass == RSURFPASS_BACKGROUND)
3080 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3081 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3082 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3086 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3088 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3089 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
3090 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
3091 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3093 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3094 if (rsurface.rtlight)
3096 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3097 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3104 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3106 // select a permutation of the lighting shader appropriate to this
3107 // combination of texture, entity, light source, and fogging, only use the
3108 // minimum features necessary to avoid wasting rendering time in the
3109 // fragment shader on features that are not being used
3110 dpuint64 permutation = 0;
3111 unsigned int mode = 0;
3112 const float *lightcolorbase = rtlight->currentcolor;
3113 float ambientscale = rtlight->ambientscale;
3114 float diffusescale = rtlight->diffusescale;
3115 float specularscale = rtlight->specularscale;
3116 // this is the location of the light in view space
3117 vec3_t viewlightorigin;
3118 // this transforms from view space (camera) to light space (cubemap)
3119 matrix4x4_t viewtolight;
3120 matrix4x4_t lighttoview;
3121 float viewtolight16f[16];
3123 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3124 if (rtlight->currentcubemap != r_texture_whitecube)
3125 permutation |= SHADERPERMUTATION_CUBEFILTER;
3126 if (diffusescale > 0)
3127 permutation |= SHADERPERMUTATION_DIFFUSE;
3128 if (specularscale > 0 && r_shadow_gloss.integer > 0)
3129 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3130 if (r_shadow_usingshadowmap2d)
3132 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3133 if (r_shadow_shadowmapvsdct)
3134 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3136 if (r_shadow_shadowmap2ddepthbuffer)
3137 permutation |= SHADERPERMUTATION_DEPTHRGB;
3139 if (vid.allowalphatocoverage)
3140 GL_AlphaToCoverage(false);
3141 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3142 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3143 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3144 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3145 switch(vid.renderpath)
3147 case RENDERPATH_D3D9:
3149 R_SetupShader_SetPermutationHLSL(mode, permutation);
3150 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3151 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3152 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3153 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3154 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3155 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3156 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3157 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);
3158 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3159 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3161 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3162 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3163 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3164 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3165 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3168 case RENDERPATH_D3D10:
3169 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3171 case RENDERPATH_D3D11:
3172 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3174 case RENDERPATH_GL20:
3175 case RENDERPATH_GLES2:
3176 R_SetupShader_SetPermutationGLSL(mode, permutation);
3177 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3178 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3179 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3180 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3181 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3182 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]);
3183 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]);
3184 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);
3185 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]);
3186 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3188 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3189 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3190 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3191 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3192 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3194 case RENDERPATH_GL11:
3195 case RENDERPATH_GL13:
3196 case RENDERPATH_GLES1:
3198 case RENDERPATH_SOFT:
3199 R_SetupShader_SetPermutationGLSL(mode, permutation);
3200 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3201 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3202 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3203 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3204 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3205 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]);
3206 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]);
3207 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);
3208 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3209 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3211 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3212 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3213 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3214 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3215 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3220 #define SKINFRAME_HASH 1024
3224 unsigned int loadsequence; // incremented each level change
3225 memexpandablearray_t array;
3226 skinframe_t *hash[SKINFRAME_HASH];
3229 r_skinframe_t r_skinframe;
3231 void R_SkinFrame_PrepareForPurge(void)
3233 r_skinframe.loadsequence++;
3234 // wrap it without hitting zero
3235 if (r_skinframe.loadsequence >= 200)
3236 r_skinframe.loadsequence = 1;
3239 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3243 // mark the skinframe as used for the purging code
3244 skinframe->loadsequence = r_skinframe.loadsequence;
3247 void R_SkinFrame_Purge(void)
3251 for (i = 0;i < SKINFRAME_HASH;i++)
3253 for (s = r_skinframe.hash[i];s;s = s->next)
3255 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3257 if (s->merged == s->base)
3259 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3260 R_PurgeTexture(s->stain );s->stain = NULL;
3261 R_PurgeTexture(s->merged);s->merged = NULL;
3262 R_PurgeTexture(s->base );s->base = NULL;
3263 R_PurgeTexture(s->pants );s->pants = NULL;
3264 R_PurgeTexture(s->shirt );s->shirt = NULL;
3265 R_PurgeTexture(s->nmap );s->nmap = NULL;
3266 R_PurgeTexture(s->gloss );s->gloss = NULL;
3267 R_PurgeTexture(s->glow );s->glow = NULL;
3268 R_PurgeTexture(s->fog );s->fog = NULL;
3269 R_PurgeTexture(s->reflect);s->reflect = NULL;
3270 s->loadsequence = 0;
3276 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3278 char basename[MAX_QPATH];
3280 Image_StripImageExtension(name, basename, sizeof(basename));
3282 if( last == NULL ) {
3284 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3285 item = r_skinframe.hash[hashindex];
3290 // linearly search through the hash bucket
3291 for( ; item ; item = item->next ) {
3292 if( !strcmp( item->basename, basename ) ) {
3299 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3303 char basename[MAX_QPATH];
3305 Image_StripImageExtension(name, basename, sizeof(basename));
3307 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3308 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3309 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3313 rtexture_t *dyntexture;
3314 // check whether its a dynamic texture
3315 dyntexture = CL_GetDynTexture( basename );
3316 if (!add && !dyntexture)
3318 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3319 memset(item, 0, sizeof(*item));
3320 strlcpy(item->basename, basename, sizeof(item->basename));
3321 item->base = dyntexture; // either NULL or dyntexture handle
3322 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3323 item->comparewidth = comparewidth;
3324 item->compareheight = compareheight;
3325 item->comparecrc = comparecrc;
3326 item->next = r_skinframe.hash[hashindex];
3327 r_skinframe.hash[hashindex] = item;
3329 else if (textureflags & TEXF_FORCE_RELOAD)
3331 rtexture_t *dyntexture;
3332 // check whether its a dynamic texture
3333 dyntexture = CL_GetDynTexture( basename );
3334 if (!add && !dyntexture)
3336 if (item->merged == item->base)
3337 item->merged = NULL;
3338 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3339 R_PurgeTexture(item->stain );item->stain = NULL;
3340 R_PurgeTexture(item->merged);item->merged = NULL;
3341 R_PurgeTexture(item->base );item->base = NULL;
3342 R_PurgeTexture(item->pants );item->pants = NULL;
3343 R_PurgeTexture(item->shirt );item->shirt = NULL;
3344 R_PurgeTexture(item->nmap );item->nmap = NULL;
3345 R_PurgeTexture(item->gloss );item->gloss = NULL;
3346 R_PurgeTexture(item->glow );item->glow = NULL;
3347 R_PurgeTexture(item->fog );item->fog = NULL;
3348 R_PurgeTexture(item->reflect);item->reflect = NULL;
3349 item->loadsequence = 0;
3351 else if( item->base == NULL )
3353 rtexture_t *dyntexture;
3354 // check whether its a dynamic texture
3355 // 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]
3356 dyntexture = CL_GetDynTexture( basename );
3357 item->base = dyntexture; // either NULL or dyntexture handle
3360 R_SkinFrame_MarkUsed(item);
3364 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3366 unsigned long long avgcolor[5], wsum; \
3374 for(pix = 0; pix < cnt; ++pix) \
3377 for(comp = 0; comp < 3; ++comp) \
3379 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3382 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3384 for(comp = 0; comp < 3; ++comp) \
3385 avgcolor[comp] += getpixel * w; \
3388 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3389 avgcolor[4] += getpixel; \
3391 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3393 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3394 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3395 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3396 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3399 extern cvar_t gl_picmip;
3400 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3403 unsigned char *pixels;
3404 unsigned char *bumppixels;
3405 unsigned char *basepixels = NULL;
3406 int basepixels_width = 0;
3407 int basepixels_height = 0;
3408 skinframe_t *skinframe;
3409 rtexture_t *ddsbase = NULL;
3410 qboolean ddshasalpha = false;
3411 float ddsavgcolor[4];
3412 char basename[MAX_QPATH];
3413 int miplevel = R_PicmipForFlags(textureflags);
3414 int savemiplevel = miplevel;
3418 if (cls.state == ca_dedicated)
3421 // return an existing skinframe if already loaded
3422 // if loading of the first image fails, don't make a new skinframe as it
3423 // would cause all future lookups of this to be missing
3424 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3425 if (skinframe && skinframe->base)
3428 Image_StripImageExtension(name, basename, sizeof(basename));
3430 // check for DDS texture file first
3431 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3433 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3434 if (basepixels == NULL)
3438 // FIXME handle miplevel
3440 if (developer_loading.integer)
3441 Con_Printf("loading skin \"%s\"\n", name);
3443 // we've got some pixels to store, so really allocate this new texture now
3445 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3446 textureflags &= ~TEXF_FORCE_RELOAD;
3447 skinframe->stain = NULL;
3448 skinframe->merged = NULL;
3449 skinframe->base = NULL;
3450 skinframe->pants = NULL;
3451 skinframe->shirt = NULL;
3452 skinframe->nmap = NULL;
3453 skinframe->gloss = NULL;
3454 skinframe->glow = NULL;
3455 skinframe->fog = NULL;
3456 skinframe->reflect = NULL;
3457 skinframe->hasalpha = false;
3458 // we could store the q2animname here too
3462 skinframe->base = ddsbase;
3463 skinframe->hasalpha = ddshasalpha;
3464 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3465 if (r_loadfog && skinframe->hasalpha)
3466 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);
3467 //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]);
3471 basepixels_width = image_width;
3472 basepixels_height = image_height;
3473 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);
3474 if (textureflags & TEXF_ALPHA)
3476 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3478 if (basepixels[j] < 255)
3480 skinframe->hasalpha = true;
3484 if (r_loadfog && skinframe->hasalpha)
3486 // has transparent pixels
3487 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3488 for (j = 0;j < image_width * image_height * 4;j += 4)
3493 pixels[j+3] = basepixels[j+3];
3495 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);
3499 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3501 //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]);
3502 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3503 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3504 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3505 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3511 mymiplevel = savemiplevel;
3512 if (r_loadnormalmap)
3513 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);
3514 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3516 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3517 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3518 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3519 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3522 // _norm is the name used by tenebrae and has been adopted as standard
3523 if (r_loadnormalmap && skinframe->nmap == NULL)
3525 mymiplevel = savemiplevel;
3526 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3528 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);
3532 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3534 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3535 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3536 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);
3538 Mem_Free(bumppixels);
3540 else if (r_shadow_bumpscale_basetexture.value > 0)
3542 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3543 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3544 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);
3548 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3549 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3553 // _luma is supported only for tenebrae compatibility
3554 // _glow is the preferred name
3555 mymiplevel = savemiplevel;
3556 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))))
3558 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);
3560 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3561 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3563 Mem_Free(pixels);pixels = NULL;
3566 mymiplevel = savemiplevel;
3567 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3569 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);
3571 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3572 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3578 mymiplevel = savemiplevel;
3579 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3581 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);
3583 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3584 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3590 mymiplevel = savemiplevel;
3591 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3593 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);
3595 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3596 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3602 mymiplevel = savemiplevel;
3603 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3605 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);
3607 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3608 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3615 Mem_Free(basepixels);
3620 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3621 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3624 skinframe_t *skinframe;
3627 if (cls.state == ca_dedicated)
3630 // if already loaded just return it, otherwise make a new skinframe
3631 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3632 if (skinframe->base)
3634 textureflags &= ~TEXF_FORCE_RELOAD;
3636 skinframe->stain = NULL;
3637 skinframe->merged = NULL;
3638 skinframe->base = NULL;
3639 skinframe->pants = NULL;
3640 skinframe->shirt = NULL;
3641 skinframe->nmap = NULL;
3642 skinframe->gloss = NULL;
3643 skinframe->glow = NULL;
3644 skinframe->fog = NULL;
3645 skinframe->reflect = NULL;
3646 skinframe->hasalpha = false;
3648 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3652 if (developer_loading.integer)
3653 Con_Printf("loading 32bit skin \"%s\"\n", name);
3655 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3657 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3658 unsigned char *b = a + width * height * 4;
3659 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3660 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);
3663 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3664 if (textureflags & TEXF_ALPHA)
3666 for (i = 3;i < width * height * 4;i += 4)
3668 if (skindata[i] < 255)
3670 skinframe->hasalpha = true;
3674 if (r_loadfog && skinframe->hasalpha)
3676 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3677 memcpy(fogpixels, skindata, width * height * 4);
3678 for (i = 0;i < width * height * 4;i += 4)
3679 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3680 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3681 Mem_Free(fogpixels);
3685 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3686 //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]);
3691 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3695 skinframe_t *skinframe;
3697 if (cls.state == ca_dedicated)
3700 // if already loaded just return it, otherwise make a new skinframe
3701 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3702 if (skinframe->base)
3704 //textureflags &= ~TEXF_FORCE_RELOAD;
3706 skinframe->stain = NULL;
3707 skinframe->merged = NULL;
3708 skinframe->base = NULL;
3709 skinframe->pants = NULL;
3710 skinframe->shirt = NULL;
3711 skinframe->nmap = NULL;
3712 skinframe->gloss = NULL;
3713 skinframe->glow = NULL;
3714 skinframe->fog = NULL;
3715 skinframe->reflect = NULL;
3716 skinframe->hasalpha = false;
3718 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3722 if (developer_loading.integer)
3723 Con_Printf("loading quake skin \"%s\"\n", name);
3725 // 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)
3726 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3727 memcpy(skinframe->qpixels, skindata, width*height);
3728 skinframe->qwidth = width;
3729 skinframe->qheight = height;
3732 for (i = 0;i < width * height;i++)
3733 featuresmask |= palette_featureflags[skindata[i]];
3735 skinframe->hasalpha = false;
3738 skinframe->hasalpha = true;
3739 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3740 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3741 skinframe->qgeneratemerged = true;
3742 skinframe->qgeneratebase = skinframe->qhascolormapping;
3743 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3745 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3746 //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]);
3751 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3755 unsigned char *skindata;
3758 if (!skinframe->qpixels)
3761 if (!skinframe->qhascolormapping)
3762 colormapped = false;
3766 if (!skinframe->qgeneratebase)
3771 if (!skinframe->qgeneratemerged)
3775 width = skinframe->qwidth;
3776 height = skinframe->qheight;
3777 skindata = skinframe->qpixels;
3779 if (skinframe->qgeneratenmap)
3781 unsigned char *a, *b;
3782 skinframe->qgeneratenmap = false;
3783 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3784 b = a + width * height * 4;
3785 // use either a custom palette or the quake palette
3786 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3787 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3788 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);
3792 if (skinframe->qgenerateglow)
3794 skinframe->qgenerateglow = false;
3795 if (skinframe->hasalpha) // fence textures
3796 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
3798 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
3803 skinframe->qgeneratebase = false;
3804 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);
3805 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);
3806 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);
3810 skinframe->qgeneratemerged = false;
3811 if (skinframe->hasalpha) // fence textures
3812 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);
3814 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);
3817 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3819 Mem_Free(skinframe->qpixels);
3820 skinframe->qpixels = NULL;
3824 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)
3827 skinframe_t *skinframe;
3830 if (cls.state == ca_dedicated)
3833 // if already loaded just return it, otherwise make a new skinframe
3834 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3835 if (skinframe->base)
3837 textureflags &= ~TEXF_FORCE_RELOAD;
3839 skinframe->stain = NULL;
3840 skinframe->merged = NULL;
3841 skinframe->base = NULL;
3842 skinframe->pants = NULL;
3843 skinframe->shirt = NULL;
3844 skinframe->nmap = NULL;
3845 skinframe->gloss = NULL;
3846 skinframe->glow = NULL;
3847 skinframe->fog = NULL;
3848 skinframe->reflect = NULL;
3849 skinframe->hasalpha = false;
3851 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3855 if (developer_loading.integer)
3856 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3858 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3859 if (textureflags & TEXF_ALPHA)
3861 for (i = 0;i < width * height;i++)
3863 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3865 skinframe->hasalpha = true;
3869 if (r_loadfog && skinframe->hasalpha)
3870 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3873 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3874 //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]);
3879 skinframe_t *R_SkinFrame_LoadMissing(void)
3881 skinframe_t *skinframe;
3883 if (cls.state == ca_dedicated)
3886 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3887 skinframe->stain = NULL;
3888 skinframe->merged = NULL;
3889 skinframe->base = NULL;
3890 skinframe->pants = NULL;
3891 skinframe->shirt = NULL;
3892 skinframe->nmap = NULL;
3893 skinframe->gloss = NULL;
3894 skinframe->glow = NULL;
3895 skinframe->fog = NULL;
3896 skinframe->reflect = NULL;
3897 skinframe->hasalpha = false;
3899 skinframe->avgcolor[0] = rand() / RAND_MAX;
3900 skinframe->avgcolor[1] = rand() / RAND_MAX;
3901 skinframe->avgcolor[2] = rand() / RAND_MAX;
3902 skinframe->avgcolor[3] = 1;
3907 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3908 typedef struct suffixinfo_s
3911 qboolean flipx, flipy, flipdiagonal;
3914 static suffixinfo_t suffix[3][6] =
3917 {"px", false, false, false},
3918 {"nx", false, false, false},
3919 {"py", false, false, false},
3920 {"ny", false, false, false},
3921 {"pz", false, false, false},
3922 {"nz", false, false, false}
3925 {"posx", false, false, false},
3926 {"negx", false, false, false},
3927 {"posy", false, false, false},
3928 {"negy", false, false, false},
3929 {"posz", false, false, false},
3930 {"negz", false, false, false}
3933 {"rt", true, false, true},
3934 {"lf", false, true, true},
3935 {"ft", true, true, false},
3936 {"bk", false, false, false},
3937 {"up", true, false, true},
3938 {"dn", true, false, true}
3942 static int componentorder[4] = {0, 1, 2, 3};
3944 static rtexture_t *R_LoadCubemap(const char *basename)
3946 int i, j, cubemapsize;
3947 unsigned char *cubemappixels, *image_buffer;
3948 rtexture_t *cubemaptexture;
3950 // must start 0 so the first loadimagepixels has no requested width/height
3952 cubemappixels = NULL;
3953 cubemaptexture = NULL;
3954 // keep trying different suffix groups (posx, px, rt) until one loads
3955 for (j = 0;j < 3 && !cubemappixels;j++)
3957 // load the 6 images in the suffix group
3958 for (i = 0;i < 6;i++)
3960 // generate an image name based on the base and and suffix
3961 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3963 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3965 // an image loaded, make sure width and height are equal
3966 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3968 // if this is the first image to load successfully, allocate the cubemap memory
3969 if (!cubemappixels && image_width >= 1)
3971 cubemapsize = image_width;
3972 // note this clears to black, so unavailable sides are black
3973 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3975 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3977 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);
3980 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3982 Mem_Free(image_buffer);
3986 // if a cubemap loaded, upload it
3989 if (developer_loading.integer)
3990 Con_Printf("loading cubemap \"%s\"\n", basename);
3992 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);
3993 Mem_Free(cubemappixels);
3997 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3998 if (developer_loading.integer)
4000 Con_Printf("(tried tried images ");
4001 for (j = 0;j < 3;j++)
4002 for (i = 0;i < 6;i++)
4003 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
4004 Con_Print(" and was unable to find any of them).\n");
4007 return cubemaptexture;
4010 rtexture_t *R_GetCubemap(const char *basename)
4013 for (i = 0;i < r_texture_numcubemaps;i++)
4014 if (r_texture_cubemaps[i] != NULL)
4015 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
4016 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
4017 if (i >= MAX_CUBEMAPS || !r_main_mempool)
4018 return r_texture_whitecube;
4019 r_texture_numcubemaps++;
4020 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
4021 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
4022 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
4023 return r_texture_cubemaps[i]->texture;
4026 static void R_Main_FreeViewCache(void)
4028 if (r_refdef.viewcache.entityvisible)
4029 Mem_Free(r_refdef.viewcache.entityvisible);
4030 if (r_refdef.viewcache.world_pvsbits)
4031 Mem_Free(r_refdef.viewcache.world_pvsbits);
4032 if (r_refdef.viewcache.world_leafvisible)
4033 Mem_Free(r_refdef.viewcache.world_leafvisible);
4034 if (r_refdef.viewcache.world_surfacevisible)
4035 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4036 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
4039 static void R_Main_ResizeViewCache(void)
4041 int numentities = r_refdef.scene.numentities;
4042 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4043 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4044 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4045 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4046 if (r_refdef.viewcache.maxentities < numentities)
4048 r_refdef.viewcache.maxentities = numentities;
4049 if (r_refdef.viewcache.entityvisible)
4050 Mem_Free(r_refdef.viewcache.entityvisible);
4051 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4053 if (r_refdef.viewcache.world_numclusters != numclusters)
4055 r_refdef.viewcache.world_numclusters = numclusters;
4056 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4057 if (r_refdef.viewcache.world_pvsbits)
4058 Mem_Free(r_refdef.viewcache.world_pvsbits);
4059 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4061 if (r_refdef.viewcache.world_numleafs != numleafs)
4063 r_refdef.viewcache.world_numleafs = numleafs;
4064 if (r_refdef.viewcache.world_leafvisible)
4065 Mem_Free(r_refdef.viewcache.world_leafvisible);
4066 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4068 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4070 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4071 if (r_refdef.viewcache.world_surfacevisible)
4072 Mem_Free(r_refdef.viewcache.world_surfacevisible);
4073 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4077 extern rtexture_t *loadingscreentexture;
4078 static void gl_main_start(void)
4080 loadingscreentexture = NULL;
4081 r_texture_blanknormalmap = NULL;
4082 r_texture_white = NULL;
4083 r_texture_grey128 = NULL;
4084 r_texture_black = NULL;
4085 r_texture_whitecube = NULL;
4086 r_texture_normalizationcube = NULL;
4087 r_texture_fogattenuation = NULL;
4088 r_texture_fogheighttexture = NULL;
4089 r_texture_gammaramps = NULL;
4090 r_texture_numcubemaps = 0;
4091 r_uniformbufferalignment = 32;
4093 r_loaddds = r_texture_dds_load.integer != 0;
4094 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4096 switch(vid.renderpath)
4098 case RENDERPATH_GL20:
4099 case RENDERPATH_D3D9:
4100 case RENDERPATH_D3D10:
4101 case RENDERPATH_D3D11:
4102 case RENDERPATH_SOFT:
4103 case RENDERPATH_GLES2:
4104 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4105 Cvar_SetValueQuick(&gl_combine, 1);
4106 Cvar_SetValueQuick(&r_glsl, 1);
4107 r_loadnormalmap = true;
4110 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4111 if (vid.support.arb_uniform_buffer_object)
4112 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4115 case RENDERPATH_GL13:
4116 case RENDERPATH_GLES1:
4117 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4118 Cvar_SetValueQuick(&gl_combine, 1);
4119 Cvar_SetValueQuick(&r_glsl, 0);
4120 r_loadnormalmap = false;
4121 r_loadgloss = false;
4124 case RENDERPATH_GL11:
4125 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4126 Cvar_SetValueQuick(&gl_combine, 0);
4127 Cvar_SetValueQuick(&r_glsl, 0);
4128 r_loadnormalmap = false;
4129 r_loadgloss = false;
4135 R_FrameData_Reset();
4136 R_BufferData_Reset();
4140 memset(r_queries, 0, sizeof(r_queries));
4142 r_qwskincache = NULL;
4143 r_qwskincache_size = 0;
4145 // due to caching of texture_t references, the collision cache must be reset
4146 Collision_Cache_Reset(true);
4148 // set up r_skinframe loading system for textures
4149 memset(&r_skinframe, 0, sizeof(r_skinframe));
4150 r_skinframe.loadsequence = 1;
4151 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4153 r_main_texturepool = R_AllocTexturePool();
4154 R_BuildBlankTextures();
4156 if (vid.support.arb_texture_cube_map)
4159 R_BuildNormalizationCube();
4161 r_texture_fogattenuation = NULL;
4162 r_texture_fogheighttexture = NULL;
4163 r_texture_gammaramps = NULL;
4164 //r_texture_fogintensity = NULL;
4165 memset(&r_fb, 0, sizeof(r_fb));
4166 r_glsl_permutation = NULL;
4167 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4168 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4170 r_hlsl_permutation = NULL;
4171 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4172 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4174 memset(&r_svbsp, 0, sizeof (r_svbsp));
4176 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4177 r_texture_numcubemaps = 0;
4179 r_refdef.fogmasktable_density = 0;
4182 // For Steelstorm Android
4183 // FIXME CACHE the program and reload
4184 // FIXME see possible combinations for SS:BR android
4185 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4186 R_SetupShader_SetPermutationGLSL(0, 12);
4187 R_SetupShader_SetPermutationGLSL(0, 13);
4188 R_SetupShader_SetPermutationGLSL(0, 8388621);
4189 R_SetupShader_SetPermutationGLSL(3, 0);
4190 R_SetupShader_SetPermutationGLSL(3, 2048);
4191 R_SetupShader_SetPermutationGLSL(5, 0);
4192 R_SetupShader_SetPermutationGLSL(5, 2);
4193 R_SetupShader_SetPermutationGLSL(5, 2048);
4194 R_SetupShader_SetPermutationGLSL(5, 8388608);
4195 R_SetupShader_SetPermutationGLSL(11, 1);
4196 R_SetupShader_SetPermutationGLSL(11, 2049);
4197 R_SetupShader_SetPermutationGLSL(11, 8193);
4198 R_SetupShader_SetPermutationGLSL(11, 10241);
4199 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4203 static void gl_main_shutdown(void)
4206 R_FrameData_Reset();
4207 R_BufferData_Reset();
4209 R_Main_FreeViewCache();
4211 switch(vid.renderpath)
4213 case RENDERPATH_GL11:
4214 case RENDERPATH_GL13:
4215 case RENDERPATH_GL20:
4216 case RENDERPATH_GLES1:
4217 case RENDERPATH_GLES2:
4218 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4220 qglDeleteQueriesARB(r_maxqueries, r_queries);
4223 case RENDERPATH_D3D9:
4224 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4226 case RENDERPATH_D3D10:
4227 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4229 case RENDERPATH_D3D11:
4230 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4232 case RENDERPATH_SOFT:
4238 memset(r_queries, 0, sizeof(r_queries));
4240 r_qwskincache = NULL;
4241 r_qwskincache_size = 0;
4243 // clear out the r_skinframe state
4244 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4245 memset(&r_skinframe, 0, sizeof(r_skinframe));
4248 Mem_Free(r_svbsp.nodes);
4249 memset(&r_svbsp, 0, sizeof (r_svbsp));
4250 R_FreeTexturePool(&r_main_texturepool);
4251 loadingscreentexture = NULL;
4252 r_texture_blanknormalmap = NULL;
4253 r_texture_white = NULL;
4254 r_texture_grey128 = NULL;
4255 r_texture_black = NULL;
4256 r_texture_whitecube = NULL;
4257 r_texture_normalizationcube = NULL;
4258 r_texture_fogattenuation = NULL;
4259 r_texture_fogheighttexture = NULL;
4260 r_texture_gammaramps = NULL;
4261 r_texture_numcubemaps = 0;
4262 //r_texture_fogintensity = NULL;
4263 memset(&r_fb, 0, sizeof(r_fb));
4266 r_glsl_permutation = NULL;
4267 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4268 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4270 r_hlsl_permutation = NULL;
4271 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4272 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4276 static void gl_main_newmap(void)
4278 // FIXME: move this code to client
4279 char *entities, entname[MAX_QPATH];
4281 Mem_Free(r_qwskincache);
4282 r_qwskincache = NULL;
4283 r_qwskincache_size = 0;
4286 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4287 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4289 CL_ParseEntityLump(entities);
4293 if (cl.worldmodel->brush.entities)
4294 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4296 R_Main_FreeViewCache();
4298 R_FrameData_Reset();
4299 R_BufferData_Reset();
4302 void GL_Main_Init(void)
4305 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4306 R_InitShaderModeInfo();
4308 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4309 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4310 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4311 if (gamemode == GAME_NEHAHRA)
4313 Cvar_RegisterVariable (&gl_fogenable);
4314 Cvar_RegisterVariable (&gl_fogdensity);
4315 Cvar_RegisterVariable (&gl_fogred);
4316 Cvar_RegisterVariable (&gl_foggreen);
4317 Cvar_RegisterVariable (&gl_fogblue);
4318 Cvar_RegisterVariable (&gl_fogstart);
4319 Cvar_RegisterVariable (&gl_fogend);
4320 Cvar_RegisterVariable (&gl_skyclip);
4322 Cvar_RegisterVariable(&r_motionblur);
4323 Cvar_RegisterVariable(&r_damageblur);
4324 Cvar_RegisterVariable(&r_motionblur_averaging);
4325 Cvar_RegisterVariable(&r_motionblur_randomize);
4326 Cvar_RegisterVariable(&r_motionblur_minblur);
4327 Cvar_RegisterVariable(&r_motionblur_maxblur);
4328 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4329 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4330 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4331 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4332 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4333 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4334 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4335 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4336 Cvar_RegisterVariable(&r_equalize_entities_by);
4337 Cvar_RegisterVariable(&r_equalize_entities_to);
4338 Cvar_RegisterVariable(&r_depthfirst);
4339 Cvar_RegisterVariable(&r_useinfinitefarclip);
4340 Cvar_RegisterVariable(&r_farclip_base);
4341 Cvar_RegisterVariable(&r_farclip_world);
4342 Cvar_RegisterVariable(&r_nearclip);
4343 Cvar_RegisterVariable(&r_deformvertexes);
4344 Cvar_RegisterVariable(&r_transparent);
4345 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4346 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4347 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4348 Cvar_RegisterVariable(&r_showoverdraw);
4349 Cvar_RegisterVariable(&r_showbboxes);
4350 Cvar_RegisterVariable(&r_showbboxes_client);
4351 Cvar_RegisterVariable(&r_showsurfaces);
4352 Cvar_RegisterVariable(&r_showtris);
4353 Cvar_RegisterVariable(&r_shownormals);
4354 Cvar_RegisterVariable(&r_showlighting);
4355 Cvar_RegisterVariable(&r_showshadowvolumes);
4356 Cvar_RegisterVariable(&r_showcollisionbrushes);
4357 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4358 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4359 Cvar_RegisterVariable(&r_showdisabledepthtest);
4360 Cvar_RegisterVariable(&r_drawportals);
4361 Cvar_RegisterVariable(&r_drawentities);
4362 Cvar_RegisterVariable(&r_draw2d);
4363 Cvar_RegisterVariable(&r_drawworld);
4364 Cvar_RegisterVariable(&r_cullentities_trace);
4365 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4366 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4367 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4368 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4369 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4370 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4371 Cvar_RegisterVariable(&r_sortentities);
4372 Cvar_RegisterVariable(&r_drawviewmodel);
4373 Cvar_RegisterVariable(&r_drawexteriormodel);
4374 Cvar_RegisterVariable(&r_speeds);
4375 Cvar_RegisterVariable(&r_fullbrights);
4376 Cvar_RegisterVariable(&r_wateralpha);
4377 Cvar_RegisterVariable(&r_dynamic);
4378 Cvar_RegisterVariable(&r_fakelight);
4379 Cvar_RegisterVariable(&r_fakelight_intensity);
4380 Cvar_RegisterVariable(&r_fullbright_directed);
4381 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4382 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4383 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4384 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4385 Cvar_RegisterVariable(&r_fullbright);
4386 Cvar_RegisterVariable(&r_shadows);
4387 Cvar_RegisterVariable(&r_shadows_darken);
4388 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4389 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4390 Cvar_RegisterVariable(&r_shadows_throwdistance);
4391 Cvar_RegisterVariable(&r_shadows_throwdirection);
4392 Cvar_RegisterVariable(&r_shadows_focus);
4393 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4394 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4395 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4396 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4397 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4398 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4399 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4400 Cvar_RegisterVariable(&r_fog_exp2);
4401 Cvar_RegisterVariable(&r_fog_clear);
4402 Cvar_RegisterVariable(&r_drawfog);
4403 Cvar_RegisterVariable(&r_transparentdepthmasking);
4404 Cvar_RegisterVariable(&r_transparent_sortmindist);
4405 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4406 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4407 Cvar_RegisterVariable(&r_texture_dds_load);
4408 Cvar_RegisterVariable(&r_texture_dds_save);
4409 Cvar_RegisterVariable(&r_textureunits);
4410 Cvar_RegisterVariable(&gl_combine);
4411 Cvar_RegisterVariable(&r_usedepthtextures);
4412 Cvar_RegisterVariable(&r_viewfbo);
4413 Cvar_RegisterVariable(&r_viewscale);
4414 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4415 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4416 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4417 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4418 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4419 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4420 Cvar_RegisterVariable(&r_glsl);
4421 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4422 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4423 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4424 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4425 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4426 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4427 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4428 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4429 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4430 Cvar_RegisterVariable(&r_glsl_postprocess);
4431 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4432 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4433 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4434 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4435 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4436 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4437 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4438 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4439 Cvar_RegisterVariable(&r_celshading);
4440 Cvar_RegisterVariable(&r_celoutlines);
4442 Cvar_RegisterVariable(&r_water);
4443 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4444 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4445 Cvar_RegisterVariable(&r_water_clippingplanebias);
4446 Cvar_RegisterVariable(&r_water_refractdistort);
4447 Cvar_RegisterVariable(&r_water_reflectdistort);
4448 Cvar_RegisterVariable(&r_water_scissormode);
4449 Cvar_RegisterVariable(&r_water_lowquality);
4450 Cvar_RegisterVariable(&r_water_hideplayer);
4451 Cvar_RegisterVariable(&r_water_fbo);
4453 Cvar_RegisterVariable(&r_lerpsprites);
4454 Cvar_RegisterVariable(&r_lerpmodels);
4455 Cvar_RegisterVariable(&r_lerplightstyles);
4456 Cvar_RegisterVariable(&r_waterscroll);
4457 Cvar_RegisterVariable(&r_bloom);
4458 Cvar_RegisterVariable(&r_bloom_colorscale);
4459 Cvar_RegisterVariable(&r_bloom_brighten);
4460 Cvar_RegisterVariable(&r_bloom_blur);
4461 Cvar_RegisterVariable(&r_bloom_resolution);
4462 Cvar_RegisterVariable(&r_bloom_colorexponent);
4463 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4464 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4465 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4466 Cvar_RegisterVariable(&r_hdr_glowintensity);
4467 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4468 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4469 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4470 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4471 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4472 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4473 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4474 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4475 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4476 Cvar_RegisterVariable(&developer_texturelogging);
4477 Cvar_RegisterVariable(&gl_lightmaps);
4478 Cvar_RegisterVariable(&r_test);
4479 Cvar_RegisterVariable(&r_batch_multidraw);
4480 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4481 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4482 Cvar_RegisterVariable(&r_glsl_skeletal);
4483 Cvar_RegisterVariable(&r_glsl_saturation);
4484 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4485 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4486 Cvar_RegisterVariable(&r_framedatasize);
4487 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4488 Cvar_RegisterVariable(&r_buffermegs[i]);
4489 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4490 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4491 Cvar_SetValue("r_fullbrights", 0);
4492 #ifdef DP_MOBILETOUCH
4493 // GLES devices have terrible depth precision in general, so...
4494 Cvar_SetValueQuick(&r_nearclip, 4);
4495 Cvar_SetValueQuick(&r_farclip_base, 4096);
4496 Cvar_SetValueQuick(&r_farclip_world, 0);
4497 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4499 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4502 void Render_Init(void)
4515 R_LightningBeams_Init();
4525 extern char *ENGINE_EXTENSIONS;
4528 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4529 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4530 gl_version = (const char *)qglGetString(GL_VERSION);
4531 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4535 if (!gl_platformextensions)
4536 gl_platformextensions = "";
4538 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4539 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4540 Con_Printf("GL_VERSION: %s\n", gl_version);
4541 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4542 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4544 VID_CheckExtensions();
4546 // LordHavoc: report supported extensions
4548 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4550 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4553 // clear to black (loading plaque will be seen over this)
4554 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4558 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4562 if (r_trippy.integer)
4564 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4566 p = r_refdef.view.frustum + i;
4571 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4575 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4579 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4583 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4587 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4591 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4595 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4599 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4607 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4611 if (r_trippy.integer)
4613 for (i = 0;i < numplanes;i++)
4620 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4624 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4628 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4632 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4636 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4640 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4644 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4648 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4656 //==================================================================================
4658 // LordHavoc: this stores temporary data used within the same frame
4660 typedef struct r_framedata_mem_s
4662 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4663 size_t size; // how much usable space
4664 size_t current; // how much space in use
4665 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4666 size_t wantedsize; // how much space was allocated
4667 unsigned char *data; // start of real data (16byte aligned)
4671 static r_framedata_mem_t *r_framedata_mem;
4673 void R_FrameData_Reset(void)
4675 while (r_framedata_mem)
4677 r_framedata_mem_t *next = r_framedata_mem->purge;
4678 Mem_Free(r_framedata_mem);
4679 r_framedata_mem = next;
4683 static void R_FrameData_Resize(qboolean mustgrow)
4686 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4687 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4688 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4690 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4691 newmem->wantedsize = wantedsize;
4692 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4693 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4694 newmem->current = 0;
4696 newmem->purge = r_framedata_mem;
4697 r_framedata_mem = newmem;
4701 void R_FrameData_NewFrame(void)
4703 R_FrameData_Resize(false);
4704 if (!r_framedata_mem)
4706 // if we ran out of space on the last frame, free the old memory now
4707 while (r_framedata_mem->purge)
4709 // repeatedly remove the second item in the list, leaving only head
4710 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4711 Mem_Free(r_framedata_mem->purge);
4712 r_framedata_mem->purge = next;
4714 // reset the current mem pointer
4715 r_framedata_mem->current = 0;
4716 r_framedata_mem->mark = 0;
4719 void *R_FrameData_Alloc(size_t size)
4724 // align to 16 byte boundary - the data pointer is already aligned, so we
4725 // only need to ensure the size of every allocation is also aligned
4726 size = (size + 15) & ~15;
4728 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4730 // emergency - we ran out of space, allocate more memory
4731 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4732 newvalue = r_framedatasize.value * 2.0f;
4733 // 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
4734 if (sizeof(size_t) >= 8)
4735 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4737 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4738 // this might not be a growing it, but we'll allocate another buffer every time
4739 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4740 R_FrameData_Resize(true);
4743 data = r_framedata_mem->data + r_framedata_mem->current;
4744 r_framedata_mem->current += size;
4746 // count the usage for stats
4747 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4748 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4750 return (void *)data;
4753 void *R_FrameData_Store(size_t size, void *data)
4755 void *d = R_FrameData_Alloc(size);
4757 memcpy(d, data, size);
4761 void R_FrameData_SetMark(void)
4763 if (!r_framedata_mem)
4765 r_framedata_mem->mark = r_framedata_mem->current;
4768 void R_FrameData_ReturnToMark(void)
4770 if (!r_framedata_mem)
4772 r_framedata_mem->current = r_framedata_mem->mark;
4775 //==================================================================================
4777 // avoid reusing the same buffer objects on consecutive frames
4778 #define R_BUFFERDATA_CYCLE 3
4780 typedef struct r_bufferdata_buffer_s
4782 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4783 size_t size; // how much usable space
4784 size_t current; // how much space in use
4785 r_meshbuffer_t *buffer; // the buffer itself
4787 r_bufferdata_buffer_t;
4789 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4790 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4792 /// frees all dynamic buffers
4793 void R_BufferData_Reset(void)
4796 r_bufferdata_buffer_t **p, *mem;
4797 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4799 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4802 p = &r_bufferdata_buffer[cycle][type];
4808 R_Mesh_DestroyMeshBuffer(mem->buffer);
4815 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4816 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4818 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4820 float newvalue = r_buffermegs[type].value;
4822 // increase the cvar if we have to (but only if we already have a mem)
4823 if (mustgrow && mem)
4825 newvalue = bound(0.25f, newvalue, 256.0f);
4826 while (newvalue * 1024*1024 < minsize)
4829 // clamp the cvar to valid range
4830 newvalue = bound(0.25f, newvalue, 256.0f);
4831 if (r_buffermegs[type].value != newvalue)
4832 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4834 // calculate size in bytes
4835 size = (size_t)(newvalue * 1024*1024);
4836 size = bound(131072, size, 256*1024*1024);
4838 // allocate a new buffer if the size is different (purge old one later)
4839 // or if we were told we must grow the buffer
4840 if (!mem || mem->size != size || mustgrow)
4842 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4845 if (type == R_BUFFERDATA_VERTEX)
4846 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4847 else if (type == R_BUFFERDATA_INDEX16)
4848 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4849 else if (type == R_BUFFERDATA_INDEX32)
4850 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4851 else if (type == R_BUFFERDATA_UNIFORM)
4852 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4853 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4854 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4858 void R_BufferData_NewFrame(void)
4861 r_bufferdata_buffer_t **p, *mem;
4862 // cycle to the next frame's buffers
4863 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4864 // if we ran out of space on the last time we used these buffers, free the old memory now
4865 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4867 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4869 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4870 // free all but the head buffer, this is how we recycle obsolete
4871 // buffers after they are no longer in use
4872 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4878 R_Mesh_DestroyMeshBuffer(mem->buffer);
4881 // reset the current offset
4882 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4887 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4889 r_bufferdata_buffer_t *mem;
4893 *returnbufferoffset = 0;
4895 // align size to a byte boundary appropriate for the buffer type, this
4896 // makes all allocations have aligned start offsets
4897 if (type == R_BUFFERDATA_UNIFORM)
4898 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4900 padsize = (datasize + 15) & ~15;
4902 // if we ran out of space in this buffer we must allocate a new one
4903 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)
4904 R_BufferData_Resize(type, true, padsize);
4906 // if the resize did not give us enough memory, fail
4907 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)
4908 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4910 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4911 offset = (int)mem->current;
4912 mem->current += padsize;
4914 // upload the data to the buffer at the chosen offset
4916 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4917 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4919 // count the usage for stats
4920 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4921 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4923 // return the buffer offset
4924 *returnbufferoffset = offset;
4929 //==================================================================================
4931 // LordHavoc: animcache originally written by Echon, rewritten since then
4934 * Animation cache prevents re-generating mesh data for an animated model
4935 * multiple times in one frame for lighting, shadowing, reflections, etc.
4938 void R_AnimCache_Free(void)
4942 void R_AnimCache_ClearCache(void)
4945 entity_render_t *ent;
4947 for (i = 0;i < r_refdef.scene.numentities;i++)
4949 ent = r_refdef.scene.entities[i];
4950 ent->animcache_vertex3f = NULL;
4951 ent->animcache_vertex3f_vertexbuffer = NULL;
4952 ent->animcache_vertex3f_bufferoffset = 0;
4953 ent->animcache_normal3f = NULL;
4954 ent->animcache_normal3f_vertexbuffer = NULL;
4955 ent->animcache_normal3f_bufferoffset = 0;
4956 ent->animcache_svector3f = NULL;
4957 ent->animcache_svector3f_vertexbuffer = NULL;
4958 ent->animcache_svector3f_bufferoffset = 0;
4959 ent->animcache_tvector3f = NULL;
4960 ent->animcache_tvector3f_vertexbuffer = NULL;
4961 ent->animcache_tvector3f_bufferoffset = 0;
4962 ent->animcache_vertexmesh = NULL;
4963 ent->animcache_vertexmesh_vertexbuffer = NULL;
4964 ent->animcache_vertexmesh_bufferoffset = 0;
4965 ent->animcache_skeletaltransform3x4 = NULL;
4966 ent->animcache_skeletaltransform3x4buffer = NULL;
4967 ent->animcache_skeletaltransform3x4offset = 0;
4968 ent->animcache_skeletaltransform3x4size = 0;
4972 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4976 // check if we need the meshbuffers
4977 if (!vid.useinterleavedarrays)
4980 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4981 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4982 // TODO: upload vertexbuffer?
4983 if (ent->animcache_vertexmesh)
4985 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4986 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4987 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4988 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4989 for (i = 0;i < numvertices;i++)
4990 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4991 if (ent->animcache_svector3f)
4992 for (i = 0;i < numvertices;i++)
4993 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4994 if (ent->animcache_tvector3f)
4995 for (i = 0;i < numvertices;i++)
4996 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4997 if (ent->animcache_normal3f)
4998 for (i = 0;i < numvertices;i++)
4999 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
5003 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
5005 dp_model_t *model = ent->model;
5008 // see if this ent is worth caching
5009 if (!model || !model->Draw || !model->AnimateVertices)
5011 // nothing to cache if it contains no animations and has no skeleton
5012 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
5014 // see if it is already cached for gpuskeletal
5015 if (ent->animcache_skeletaltransform3x4)
5017 // see if it is already cached as a mesh
5018 if (ent->animcache_vertex3f)
5020 // check if we need to add normals or tangents
5021 if (ent->animcache_normal3f)
5022 wantnormals = false;
5023 if (ent->animcache_svector3f)
5024 wanttangents = false;
5025 if (!wantnormals && !wanttangents)
5029 // check which kind of cache we need to generate
5030 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
5032 // cache the skeleton so the vertex shader can use it
5033 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
5034 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
5035 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
5036 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
5037 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
5038 // note: this can fail if the buffer is at the grow limit
5039 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
5040 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
5042 else if (ent->animcache_vertex3f)
5044 // mesh was already cached but we may need to add normals/tangents
5045 // (this only happens with multiple views, reflections, cameras, etc)
5046 if (wantnormals || wanttangents)
5048 numvertices = model->surfmesh.num_vertices;
5050 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5053 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5054 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5056 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5057 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5058 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5059 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5060 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5065 // generate mesh cache
5066 numvertices = model->surfmesh.num_vertices;
5067 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5069 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5072 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5073 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5075 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5076 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5077 if (wantnormals || wanttangents)
5079 r_refdef.stats[r_stat_animcache_shade_count] += 1;
5080 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5081 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5083 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5084 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5085 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5090 void R_AnimCache_CacheVisibleEntities(void)
5093 qboolean wantnormals = true;
5094 qboolean wanttangents = !r_showsurfaces.integer;
5096 switch(vid.renderpath)
5098 case RENDERPATH_GL20:
5099 case RENDERPATH_D3D9:
5100 case RENDERPATH_D3D10:
5101 case RENDERPATH_D3D11:
5102 case RENDERPATH_GLES2:
5104 case RENDERPATH_GL11:
5105 case RENDERPATH_GL13:
5106 case RENDERPATH_GLES1:
5107 wanttangents = false;
5109 case RENDERPATH_SOFT:
5113 if (r_shownormals.integer)
5114 wanttangents = wantnormals = true;
5116 // TODO: thread this
5117 // NOTE: R_PrepareRTLights() also caches entities
5119 for (i = 0;i < r_refdef.scene.numentities;i++)
5120 if (r_refdef.viewcache.entityvisible[i])
5121 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5124 //==================================================================================
5126 extern cvar_t r_overheadsprites_pushback;
5128 static void R_GetDirectedFullbright(vec3_t ambient, vec3_t diffuse, vec3_t worldspacenormal)
5132 VectorSet(ambient, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value, r_fullbright_directed_ambient.value);
5133 VectorSet(diffuse, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value, r_fullbright_directed_diffuse.value);
5135 // Use cl.viewangles and not r_refdef.view.forward here so it is the
5136 // same for all stereo views, and to better handle pitches outside
5137 // [-90, 90] (in_pitch_* cvars allow that).
5138 VectorCopy(cl.viewangles, angles);
5139 if (r_fullbright_directed_pitch_relative.integer) {
5140 angles[PITCH] += r_fullbright_directed_pitch.value;
5142 angles[PITCH] = r_fullbright_directed_pitch.value;
5144 AngleVectors(angles, worldspacenormal, NULL, NULL);
5145 VectorNegate(worldspacenormal, worldspacenormal);
5148 static void R_View_UpdateEntityLighting (void)
5151 entity_render_t *ent;
5152 vec3_t tempdiffusenormal, avg;
5153 vec_t f, fa, fd, fdd;
5154 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5156 for (i = 0;i < r_refdef.scene.numentities;i++)
5158 ent = r_refdef.scene.entities[i];
5160 // skip unseen models
5161 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5165 if (ent->model && ent->model == cl.worldmodel)
5167 // TODO: use modellight for r_ambient settings on world?
5168 // The logic here currently matches RSurf_ActiveWorldEntity.
5169 if (r_fullbright_directed.integer && (r_fullbright.integer || !ent->model || !ent->model->lit))
5171 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5172 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5173 if(VectorLength2(ent->modellight_lightdir) == 0)
5174 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5175 VectorNormalize(ent->modellight_lightdir);
5179 VectorSet(ent->modellight_ambient, 0, 0, 0);
5180 VectorSet(ent->modellight_diffuse, 0, 0, 0);
5181 VectorSet(ent->modellight_lightdir, 0, 0, 1);
5186 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5188 // aleady updated by CSQC
5189 // TODO: force modellight on BSP models in this case?
5190 VectorCopy(ent->modellight_lightdir, tempdiffusenormal);
5194 // fetch the lighting from the worldmodel data
5195 VectorClear(ent->modellight_ambient);
5196 VectorClear(ent->modellight_diffuse);
5197 VectorClear(tempdiffusenormal);
5198 if (ent->flags & RENDER_LIGHT)
5201 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5203 // complete lightning for lit sprites
5204 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5205 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5207 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5208 org[2] = org[2] + r_overheadsprites_pushback.value;
5209 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5211 else if (!r_fullbright.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->lit && r_refdef.scene.worldmodel->brush.LightPoint)
5213 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5215 else if (r_fullbright_directed.integer)
5217 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5221 VectorSet(ent->modellight_ambient, 1, 1, 1);
5224 if(ent->flags & RENDER_EQUALIZE)
5226 // first fix up ambient lighting...
5227 if(r_equalize_entities_minambient.value > 0)
5229 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5232 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5233 if(fa < r_equalize_entities_minambient.value * fd)
5236 // fa'/fd' = minambient
5237 // fa'+0.25*fd' = fa+0.25*fd
5239 // fa' = fd' * minambient
5240 // fd'*(0.25+minambient) = fa+0.25*fd
5242 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5243 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5245 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5246 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
5247 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5248 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5253 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5255 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5256 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5260 // adjust brightness and saturation to target
5261 avg[0] = avg[1] = avg[2] = fa / f;
5262 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5263 avg[0] = avg[1] = avg[2] = fd / f;
5264 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5271 // EF_FULLBRIGHT entity.
5272 if (r_fullbright_directed.integer)
5274 R_GetDirectedFullbright(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
5278 VectorSet(ent->modellight_ambient, 1, 1, 1);
5283 // move the light direction into modelspace coordinates for lighting code
5284 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5285 if(VectorLength2(ent->modellight_lightdir) == 0)
5286 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5287 VectorNormalize(ent->modellight_lightdir);
5291 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5294 vec3_t eyemins, eyemaxs;
5295 vec3_t boxmins, boxmaxs;
5298 dp_model_t *model = r_refdef.scene.worldmodel;
5299 static vec3_t positions[] = {
5300 { 0.5f, 0.5f, 0.5f },
5301 { 0.0f, 0.0f, 0.0f },
5302 { 0.0f, 0.0f, 1.0f },
5303 { 0.0f, 1.0f, 0.0f },
5304 { 0.0f, 1.0f, 1.0f },
5305 { 1.0f, 0.0f, 0.0f },
5306 { 1.0f, 0.0f, 1.0f },
5307 { 1.0f, 1.0f, 0.0f },
5308 { 1.0f, 1.0f, 1.0f },
5311 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5315 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5316 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5319 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5322 // expand the eye box a little
5323 eyemins[0] = eye[0] - eyejitter;
5324 eyemaxs[0] = eye[0] + eyejitter;
5325 eyemins[1] = eye[1] - eyejitter;
5326 eyemaxs[1] = eye[1] + eyejitter;
5327 eyemins[2] = eye[2] - eyejitter;
5328 eyemaxs[2] = eye[2] + eyejitter;
5329 // expand the box a little
5330 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0];
5331 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0];
5332 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1];
5333 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1];
5334 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2];
5335 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2];
5337 // return true if eye overlaps enlarged box
5338 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5341 // try specific positions in the box first - note that these can be cached
5342 if (r_cullentities_trace_entityocclusion.integer)
5344 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5346 VectorCopy(eye, start);
5347 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5348 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5349 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5350 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5351 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5352 // not picky - if the trace ended anywhere in the box we're good
5353 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5357 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5360 // try various random positions
5361 for (i = 0; i < numsamples; i++)
5363 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5364 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5365 if (r_cullentities_trace_entityocclusion.integer)
5367 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5368 // not picky - if the trace ended anywhere in the box we're good
5369 if (BoxesOverlap(trace.endpos, trace.endpos, boxmins, boxmaxs))
5372 else if (model->brush.TraceLineOfSight(model, start, end, boxmins, boxmaxs))
5380 static void R_View_UpdateEntityVisible (void)
5385 entity_render_t *ent;
5387 if (r_refdef.envmap || r_fb.water.hideplayer)
5388 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5389 else if (chase_active.integer || r_fb.water.renderingscene)
5390 renderimask = RENDER_VIEWMODEL;
5392 renderimask = RENDER_EXTERIORMODEL;
5393 if (!r_drawviewmodel.integer)
5394 renderimask |= RENDER_VIEWMODEL;
5395 if (!r_drawexteriormodel.integer)
5396 renderimask |= RENDER_EXTERIORMODEL;
5397 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5398 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5400 // worldmodel can check visibility
5401 for (i = 0;i < r_refdef.scene.numentities;i++)
5403 ent = r_refdef.scene.entities[i];
5404 if (!(ent->flags & renderimask))
5405 if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
5406 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))
5407 r_refdef.viewcache.entityvisible[i] = true;
5412 // no worldmodel or it can't check visibility
5413 for (i = 0;i < r_refdef.scene.numentities;i++)
5415 ent = r_refdef.scene.entities[i];
5416 if (!(ent->flags & renderimask))
5417 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)))
5418 r_refdef.viewcache.entityvisible[i] = true;
5421 if (r_cullentities_trace.integer)
5423 for (i = 0;i < r_refdef.scene.numentities;i++)
5425 if (!r_refdef.viewcache.entityvisible[i])
5427 ent = r_refdef.scene.entities[i];
5428 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5430 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5431 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5432 ent->last_trace_visibility = realtime;
5433 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5434 r_refdef.viewcache.entityvisible[i] = 0;
5440 /// only used if skyrendermasked, and normally returns false
5441 static int R_DrawBrushModelsSky (void)
5444 entity_render_t *ent;
5447 for (i = 0;i < r_refdef.scene.numentities;i++)
5449 if (!r_refdef.viewcache.entityvisible[i])
5451 ent = r_refdef.scene.entities[i];
5452 if (!ent->model || !ent->model->DrawSky)
5454 ent->model->DrawSky(ent);
5460 static void R_DrawNoModel(entity_render_t *ent);
5461 static void R_DrawModels(void)
5464 entity_render_t *ent;
5466 for (i = 0;i < r_refdef.scene.numentities;i++)
5468 if (!r_refdef.viewcache.entityvisible[i])
5470 ent = r_refdef.scene.entities[i];
5471 r_refdef.stats[r_stat_entities]++;
5473 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5476 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5477 Con_Printf("R_DrawModels\n");
5478 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]);
5479 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);
5480 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);
5483 if (ent->model && ent->model->Draw != NULL)
5484 ent->model->Draw(ent);
5490 static void R_DrawModelsDepth(void)
5493 entity_render_t *ent;
5495 for (i = 0;i < r_refdef.scene.numentities;i++)
5497 if (!r_refdef.viewcache.entityvisible[i])
5499 ent = r_refdef.scene.entities[i];
5500 if (ent->model && ent->model->DrawDepth != NULL)
5501 ent->model->DrawDepth(ent);
5505 static void R_DrawModelsDebug(void)
5508 entity_render_t *ent;
5510 for (i = 0;i < r_refdef.scene.numentities;i++)
5512 if (!r_refdef.viewcache.entityvisible[i])
5514 ent = r_refdef.scene.entities[i];
5515 if (ent->model && ent->model->DrawDebug != NULL)
5516 ent->model->DrawDebug(ent);
5520 static void R_DrawModelsAddWaterPlanes(void)
5523 entity_render_t *ent;
5525 for (i = 0;i < r_refdef.scene.numentities;i++)
5527 if (!r_refdef.viewcache.entityvisible[i])
5529 ent = r_refdef.scene.entities[i];
5530 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5531 ent->model->DrawAddWaterPlanes(ent);
5535 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}};
5537 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5539 if (r_hdr_irisadaptation.integer)
5544 vec3_t diffusenormal;
5546 vec_t brightness = 0.0f;
5551 VectorCopy(r_refdef.view.forward, forward);
5552 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5554 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5555 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5556 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5557 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5558 d = DotProduct(forward, diffusenormal);
5559 brightness += VectorLength(ambient);
5561 brightness += d * VectorLength(diffuse);
5563 brightness *= 1.0f / c;
5564 brightness += 0.00001f; // make sure it's never zero
5565 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5566 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5567 current = r_hdr_irisadaptation_value.value;
5569 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5570 else if (current > goal)
5571 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5572 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5573 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5575 else if (r_hdr_irisadaptation_value.value != 1.0f)
5576 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5579 static void R_View_SetFrustum(const int *scissor)
5582 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5583 vec3_t forward, left, up, origin, v;
5587 // flipped x coordinates (because x points left here)
5588 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5589 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5591 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5592 switch(vid.renderpath)
5594 case RENDERPATH_D3D9:
5595 case RENDERPATH_D3D10:
5596 case RENDERPATH_D3D11:
5597 // non-flipped y coordinates
5598 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5599 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5601 case RENDERPATH_SOFT:
5602 case RENDERPATH_GL11:
5603 case RENDERPATH_GL13:
5604 case RENDERPATH_GL20:
5605 case RENDERPATH_GLES1:
5606 case RENDERPATH_GLES2:
5607 // non-flipped y coordinates
5608 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5609 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5614 // we can't trust r_refdef.view.forward and friends in reflected scenes
5615 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5618 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5619 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5620 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5621 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5622 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5623 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5624 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5625 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5626 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5627 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5628 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5629 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5633 zNear = r_refdef.nearclip;
5634 nudge = 1.0 - 1.0 / (1<<23);
5635 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5636 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5637 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5638 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5639 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5640 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5641 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5642 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5648 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5649 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5650 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5651 r_refdef.view.frustum[0].dist = m[15] - m[12];
5653 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5654 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5655 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5656 r_refdef.view.frustum[1].dist = m[15] + m[12];
5658 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5659 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5660 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5661 r_refdef.view.frustum[2].dist = m[15] - m[13];
5663 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5664 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5665 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5666 r_refdef.view.frustum[3].dist = m[15] + m[13];
5668 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5669 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5670 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5671 r_refdef.view.frustum[4].dist = m[15] - m[14];
5673 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5674 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5675 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5676 r_refdef.view.frustum[5].dist = m[15] + m[14];
5679 if (r_refdef.view.useperspective)
5681 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5682 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]);
5683 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]);
5684 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]);
5685 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]);
5687 // then the normals from the corners relative to origin
5688 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5689 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5690 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5691 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5693 // in a NORMAL view, forward cross left == up
5694 // in a REFLECTED view, forward cross left == down
5695 // so our cross products above need to be adjusted for a left handed coordinate system
5696 CrossProduct(forward, left, v);
5697 if(DotProduct(v, up) < 0)
5699 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5700 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5701 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5702 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5705 // Leaving those out was a mistake, those were in the old code, and they
5706 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5707 // I couldn't reproduce it after adding those normalizations. --blub
5708 VectorNormalize(r_refdef.view.frustum[0].normal);
5709 VectorNormalize(r_refdef.view.frustum[1].normal);
5710 VectorNormalize(r_refdef.view.frustum[2].normal);
5711 VectorNormalize(r_refdef.view.frustum[3].normal);
5713 // make the corners absolute
5714 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5715 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5716 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5717 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5720 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5722 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5723 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5724 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5725 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5726 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5730 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5731 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5732 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5733 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5734 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5735 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5736 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5737 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5738 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5739 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5741 r_refdef.view.numfrustumplanes = 5;
5743 if (r_refdef.view.useclipplane)
5745 r_refdef.view.numfrustumplanes = 6;
5746 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5749 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5750 PlaneClassify(r_refdef.view.frustum + i);
5752 // LordHavoc: note to all quake engine coders, Quake had a special case
5753 // for 90 degrees which assumed a square view (wrong), so I removed it,
5754 // Quake2 has it disabled as well.
5756 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5757 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5758 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5759 //PlaneClassify(&frustum[0]);
5761 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5762 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5763 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5764 //PlaneClassify(&frustum[1]);
5766 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5767 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5768 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5769 //PlaneClassify(&frustum[2]);
5771 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5772 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5773 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5774 //PlaneClassify(&frustum[3]);
5777 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5778 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5779 //PlaneClassify(&frustum[4]);
5782 static void R_View_UpdateWithScissor(const int *myscissor)
5784 R_Main_ResizeViewCache();
5785 R_View_SetFrustum(myscissor);
5786 R_View_WorldVisibility(r_refdef.view.useclipplane);
5787 R_View_UpdateEntityVisible();
5788 R_View_UpdateEntityLighting();
5791 static void R_View_Update(void)
5793 R_Main_ResizeViewCache();
5794 R_View_SetFrustum(NULL);
5795 R_View_WorldVisibility(r_refdef.view.useclipplane);
5796 R_View_UpdateEntityVisible();
5797 R_View_UpdateEntityLighting();
5800 float viewscalefpsadjusted = 1.0f;
5802 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5804 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5805 scale = bound(0.03125f, scale, 1.0f);
5806 *outwidth = (int)ceil(width * scale);
5807 *outheight = (int)ceil(height * scale);
5810 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5812 const float *customclipplane = NULL;
5814 int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5815 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5817 // LordHavoc: couldn't figure out how to make this approach the
5818 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5819 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5820 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5821 dist = r_refdef.view.clipplane.dist;
5822 plane[0] = r_refdef.view.clipplane.normal[0];
5823 plane[1] = r_refdef.view.clipplane.normal[1];
5824 plane[2] = r_refdef.view.clipplane.normal[2];
5826 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5829 //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5830 rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5832 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5833 if (!r_refdef.view.useperspective)
5834 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);
5835 else if (vid.stencil && r_useinfinitefarclip.integer)
5836 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);
5838 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);
5839 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5840 R_SetViewport(&r_refdef.view.viewport);
5841 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5843 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5844 float screenplane[4];
5845 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5846 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5847 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5848 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5849 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5853 void R_EntityMatrix(const matrix4x4_t *matrix)
5855 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5857 gl_modelmatrixchanged = false;
5858 gl_modelmatrix = *matrix;
5859 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5860 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5861 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5862 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5864 switch(vid.renderpath)
5866 case RENDERPATH_D3D9:
5868 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5869 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5872 case RENDERPATH_D3D10:
5873 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5875 case RENDERPATH_D3D11:
5876 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5878 case RENDERPATH_GL11:
5879 case RENDERPATH_GL13:
5880 case RENDERPATH_GLES1:
5882 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5885 case RENDERPATH_SOFT:
5886 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5887 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5889 case RENDERPATH_GL20:
5890 case RENDERPATH_GLES2:
5891 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5892 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5898 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5900 r_viewport_t viewport;
5904 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5905 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);
5906 R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5907 R_SetViewport(&viewport);
5908 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5909 GL_Color(1, 1, 1, 1);
5910 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5911 GL_BlendFunc(GL_ONE, GL_ZERO);
5912 GL_ScissorTest(false);
5913 GL_DepthMask(false);
5914 GL_DepthRange(0, 1);
5915 GL_DepthTest(false);
5916 GL_DepthFunc(GL_LEQUAL);
5917 R_EntityMatrix(&identitymatrix);
5918 R_Mesh_ResetTextureState();
5919 GL_PolygonOffset(0, 0);
5920 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5921 switch(vid.renderpath)
5923 case RENDERPATH_GL11:
5924 case RENDERPATH_GL13:
5925 case RENDERPATH_GL20:
5926 case RENDERPATH_GLES1:
5927 case RENDERPATH_GLES2:
5928 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5930 case RENDERPATH_D3D9:
5931 case RENDERPATH_D3D10:
5932 case RENDERPATH_D3D11:
5933 case RENDERPATH_SOFT:
5936 GL_CullFace(GL_NONE);
5941 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5945 R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5948 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5952 R_SetupView(true, fbo, depthtexture, colortexture);
5953 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5954 GL_Color(1, 1, 1, 1);
5955 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5956 GL_BlendFunc(GL_ONE, GL_ZERO);
5957 GL_ScissorTest(true);
5959 GL_DepthRange(0, 1);
5961 GL_DepthFunc(GL_LEQUAL);
5962 R_EntityMatrix(&identitymatrix);
5963 R_Mesh_ResetTextureState();
5964 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5965 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5966 switch(vid.renderpath)
5968 case RENDERPATH_GL11:
5969 case RENDERPATH_GL13:
5970 case RENDERPATH_GL20:
5971 case RENDERPATH_GLES1:
5972 case RENDERPATH_GLES2:
5973 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5975 case RENDERPATH_D3D9:
5976 case RENDERPATH_D3D10:
5977 case RENDERPATH_D3D11:
5978 case RENDERPATH_SOFT:
5981 GL_CullFace(r_refdef.view.cullface_back);
5986 R_RenderView_UpdateViewVectors
5989 void R_RenderView_UpdateViewVectors(void)
5991 // break apart the view matrix into vectors for various purposes
5992 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5993 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5994 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5995 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5996 // make an inverted copy of the view matrix for tracking sprites
5997 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
6000 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
6001 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
6003 static void R_Water_StartFrame(void)
6006 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
6007 r_waterstate_waterplane_t *p;
6008 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;
6010 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
6013 switch(vid.renderpath)
6015 case RENDERPATH_GL20:
6016 case RENDERPATH_D3D9:
6017 case RENDERPATH_D3D10:
6018 case RENDERPATH_D3D11:
6019 case RENDERPATH_SOFT:
6020 case RENDERPATH_GLES2:
6022 case RENDERPATH_GL11:
6023 case RENDERPATH_GL13:
6024 case RENDERPATH_GLES1:
6028 // set waterwidth and waterheight to the water resolution that will be
6029 // used (often less than the screen resolution for faster rendering)
6030 R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
6032 // calculate desired texture sizes
6033 // can't use water if the card does not support the texture size
6034 if (!r_water.integer || r_showsurfaces.integer)
6035 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
6036 else if (vid.support.arb_texture_non_power_of_two)
6038 texturewidth = waterwidth;
6039 textureheight = waterheight;
6040 camerawidth = waterwidth;
6041 cameraheight = waterheight;
6045 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
6046 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
6047 for (camerawidth = 1;camerawidth * 2 <= waterwidth ;camerawidth *= 2);
6048 for (cameraheight = 1;cameraheight * 2 <= waterheight;cameraheight *= 2);
6051 // allocate textures as needed
6052 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))
6054 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6055 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
6057 if (p->texture_refraction)
6058 R_FreeTexture(p->texture_refraction);
6059 p->texture_refraction = NULL;
6060 if (p->fbo_refraction)
6061 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
6062 p->fbo_refraction = 0;
6063 if (p->texture_reflection)
6064 R_FreeTexture(p->texture_reflection);
6065 p->texture_reflection = NULL;
6066 if (p->fbo_reflection)
6067 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
6068 p->fbo_reflection = 0;
6069 if (p->texture_camera)
6070 R_FreeTexture(p->texture_camera);
6071 p->texture_camera = NULL;
6073 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
6076 memset(&r_fb.water, 0, sizeof(r_fb.water));
6077 r_fb.water.texturewidth = texturewidth;
6078 r_fb.water.textureheight = textureheight;
6079 r_fb.water.camerawidth = camerawidth;
6080 r_fb.water.cameraheight = cameraheight;
6083 if (r_fb.water.texturewidth)
6085 int scaledwidth, scaledheight;
6087 r_fb.water.enabled = true;
6089 // water resolution is usually reduced
6090 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
6091 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
6092 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
6094 // set up variables that will be used in shader setup
6095 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6096 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6097 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
6098 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
6101 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
6102 r_fb.water.numwaterplanes = 0;
6105 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
6107 int planeindex, bestplaneindex, vertexindex;
6108 vec3_t mins, maxs, normal, center, v, n;
6109 vec_t planescore, bestplanescore;
6111 r_waterstate_waterplane_t *p;
6112 texture_t *t = R_GetCurrentTexture(surface->texture);
6114 rsurface.texture = t;
6115 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
6116 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
6117 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
6119 // average the vertex normals, find the surface bounds (after deformvertexes)
6120 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
6121 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
6122 VectorCopy(n, normal);
6123 VectorCopy(v, mins);
6124 VectorCopy(v, maxs);
6125 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
6127 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
6128 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
6129 VectorAdd(normal, n, normal);
6130 mins[0] = min(mins[0], v[0]);
6131 mins[1] = min(mins[1], v[1]);
6132 mins[2] = min(mins[2], v[2]);
6133 maxs[0] = max(maxs[0], v[0]);
6134 maxs[1] = max(maxs[1], v[1]);
6135 maxs[2] = max(maxs[2], v[2]);
6137 VectorNormalize(normal);
6138 VectorMAM(0.5f, mins, 0.5f, maxs, center);
6140 VectorCopy(normal, plane.normal);
6141 VectorNormalize(plane.normal);
6142 plane.dist = DotProduct(center, plane.normal);
6143 PlaneClassify(&plane);
6144 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6146 // skip backfaces (except if nocullface is set)
6147 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6149 VectorNegate(plane.normal, plane.normal);
6151 PlaneClassify(&plane);
6155 // find a matching plane if there is one
6156 bestplaneindex = -1;
6157 bestplanescore = 1048576.0f;
6158 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6160 if(p->camera_entity == t->camera_entity)
6162 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6163 if (bestplaneindex < 0 || bestplanescore > planescore)
6165 bestplaneindex = planeindex;
6166 bestplanescore = planescore;
6170 planeindex = bestplaneindex;
6172 // if this surface does not fit any known plane rendered this frame, add one
6173 if (planeindex < 0 || bestplanescore > 0.001f)
6175 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6177 // store the new plane
6178 planeindex = r_fb.water.numwaterplanes++;
6179 p = r_fb.water.waterplanes + planeindex;
6181 // clear materialflags and pvs
6182 p->materialflags = 0;
6183 p->pvsvalid = false;
6184 p->camera_entity = t->camera_entity;
6185 VectorCopy(mins, p->mins);
6186 VectorCopy(maxs, p->maxs);
6190 // We're totally screwed.
6196 // merge mins/maxs when we're adding this surface to the plane
6197 p = r_fb.water.waterplanes + planeindex;
6198 p->mins[0] = min(p->mins[0], mins[0]);
6199 p->mins[1] = min(p->mins[1], mins[1]);
6200 p->mins[2] = min(p->mins[2], mins[2]);
6201 p->maxs[0] = max(p->maxs[0], maxs[0]);
6202 p->maxs[1] = max(p->maxs[1], maxs[1]);
6203 p->maxs[2] = max(p->maxs[2], maxs[2]);
6205 // merge this surface's materialflags into the waterplane
6206 p->materialflags |= t->currentmaterialflags;
6207 if(!(p->materialflags & MATERIALFLAG_CAMERA))
6209 // merge this surface's PVS into the waterplane
6210 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6211 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6213 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6219 extern cvar_t r_drawparticles;
6220 extern cvar_t r_drawdecals;
6222 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6225 r_refdef_view_t originalview;
6226 r_refdef_view_t myview;
6227 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;
6228 r_waterstate_waterplane_t *p;
6230 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;
6233 originalview = r_refdef.view;
6235 // lowquality hack, temporarily shut down some cvars and restore afterwards
6236 qualityreduction = r_water_lowquality.integer;
6237 if (qualityreduction > 0)
6239 if (qualityreduction >= 1)
6241 old_r_shadows = r_shadows.integer;
6242 old_r_worldrtlight = r_shadow_realtime_world.integer;
6243 old_r_dlight = r_shadow_realtime_dlight.integer;
6244 Cvar_SetValueQuick(&r_shadows, 0);
6245 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6246 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6248 if (qualityreduction >= 2)
6250 old_r_dynamic = r_dynamic.integer;
6251 old_r_particles = r_drawparticles.integer;
6252 old_r_decals = r_drawdecals.integer;
6253 Cvar_SetValueQuick(&r_dynamic, 0);
6254 Cvar_SetValueQuick(&r_drawparticles, 0);
6255 Cvar_SetValueQuick(&r_drawdecals, 0);
6259 // make sure enough textures are allocated
6260 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6262 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6264 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6266 if (!p->texture_refraction)
6267 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);
6268 if (!p->texture_refraction)
6272 if (r_fb.water.depthtexture == NULL)
6273 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6274 if (p->fbo_refraction == 0)
6275 p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6278 else if (p->materialflags & MATERIALFLAG_CAMERA)
6280 if (!p->texture_camera)
6281 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);
6282 if (!p->texture_camera)
6286 if (r_fb.water.depthtexture == NULL)
6287 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6288 if (p->fbo_camera == 0)
6289 p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6293 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6295 if (!p->texture_reflection)
6296 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);
6297 if (!p->texture_reflection)
6301 if (r_fb.water.depthtexture == NULL)
6302 r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6303 if (p->fbo_reflection == 0)
6304 p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6310 r_refdef.view = originalview;
6311 r_refdef.view.showdebug = false;
6312 r_refdef.view.width = r_fb.water.waterwidth;
6313 r_refdef.view.height = r_fb.water.waterheight;
6314 r_refdef.view.useclipplane = true;
6315 myview = r_refdef.view;
6316 r_fb.water.renderingscene = true;
6317 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6319 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6321 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6323 r_refdef.view = myview;
6324 if(r_water_scissormode.integer)
6326 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6327 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6328 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6331 // render reflected scene and copy into texture
6332 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6333 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6334 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6335 r_refdef.view.clipplane = p->plane;
6336 // reverse the cullface settings for this render
6337 r_refdef.view.cullface_front = GL_FRONT;
6338 r_refdef.view.cullface_back = GL_BACK;
6339 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6341 r_refdef.view.usecustompvs = true;
6343 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6345 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6348 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6349 R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6350 R_ClearScreen(r_refdef.fogenabled);
6351 if(r_water_scissormode.integer & 2)
6352 R_View_UpdateWithScissor(myscissor);
6355 R_AnimCache_CacheVisibleEntities();
6356 if(r_water_scissormode.integer & 1)
6357 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6358 R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6360 if (!p->fbo_reflection)
6361 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);
6362 r_fb.water.hideplayer = false;
6365 // render the normal view scene and copy into texture
6366 // (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)
6367 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6369 r_refdef.view = myview;
6370 if(r_water_scissormode.integer)
6372 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6373 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6374 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6377 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6379 r_refdef.view.clipplane = p->plane;
6380 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6381 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6383 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6385 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6386 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6387 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6388 R_RenderView_UpdateViewVectors();
6389 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6391 r_refdef.view.usecustompvs = true;
6392 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);
6396 PlaneClassify(&r_refdef.view.clipplane);
6398 R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6399 R_ClearScreen(r_refdef.fogenabled);
6400 if(r_water_scissormode.integer & 2)
6401 R_View_UpdateWithScissor(myscissor);
6404 R_AnimCache_CacheVisibleEntities();
6405 if(r_water_scissormode.integer & 1)
6406 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6407 R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6409 if (!p->fbo_refraction)
6410 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);
6411 r_fb.water.hideplayer = false;
6413 else if (p->materialflags & MATERIALFLAG_CAMERA)
6415 r_refdef.view = myview;
6417 r_refdef.view.clipplane = p->plane;
6418 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6419 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6421 r_refdef.view.width = r_fb.water.camerawidth;
6422 r_refdef.view.height = r_fb.water.cameraheight;
6423 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6424 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6425 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6426 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6428 if(p->camera_entity)
6430 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6431 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6434 // note: all of the view is used for displaying... so
6435 // there is no use in scissoring
6437 // reverse the cullface settings for this render
6438 r_refdef.view.cullface_front = GL_FRONT;
6439 r_refdef.view.cullface_back = GL_BACK;
6440 // also reverse the view matrix
6441 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
6442 R_RenderView_UpdateViewVectors();
6443 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6445 r_refdef.view.usecustompvs = true;
6446 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);
6449 // camera needs no clipplane
6450 r_refdef.view.useclipplane = false;
6452 PlaneClassify(&r_refdef.view.clipplane);
6454 r_fb.water.hideplayer = false;
6456 R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6457 R_ClearScreen(r_refdef.fogenabled);
6459 R_AnimCache_CacheVisibleEntities();
6460 R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6463 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);
6464 r_fb.water.hideplayer = false;
6468 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6469 r_fb.water.renderingscene = false;
6470 r_refdef.view = originalview;
6471 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6472 if (!r_fb.water.depthtexture)
6473 R_ClearScreen(r_refdef.fogenabled);
6475 R_AnimCache_CacheVisibleEntities();
6478 r_refdef.view = originalview;
6479 r_fb.water.renderingscene = false;
6480 Cvar_SetValueQuick(&r_water, 0);
6481 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6483 // lowquality hack, restore cvars
6484 if (qualityreduction > 0)
6486 if (qualityreduction >= 1)
6488 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6489 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6490 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6492 if (qualityreduction >= 2)
6494 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6495 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6496 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6501 static void R_Bloom_StartFrame(void)
6504 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6505 int viewwidth, viewheight;
6506 qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6507 textype_t textype = TEXTYPE_COLORBUFFER;
6509 switch (vid.renderpath)
6511 case RENDERPATH_GL20:
6512 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6513 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6515 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6516 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6519 case RENDERPATH_GL11:
6520 case RENDERPATH_GL13:
6521 case RENDERPATH_GLES1:
6522 case RENDERPATH_GLES2:
6523 case RENDERPATH_D3D9:
6524 case RENDERPATH_D3D10:
6525 case RENDERPATH_D3D11:
6526 r_fb.usedepthtextures = false;
6528 case RENDERPATH_SOFT:
6529 r_fb.usedepthtextures = true;
6533 if (r_viewscale_fpsscaling.integer)
6535 double actualframetime;
6536 double targetframetime;
6538 actualframetime = r_refdef.lastdrawscreentime;
6539 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6540 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6541 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6542 if (r_viewscale_fpsscaling_stepsize.value > 0)
6543 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6544 viewscalefpsadjusted += adjust;
6545 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6548 viewscalefpsadjusted = 1.0f;
6550 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6552 switch(vid.renderpath)
6554 case RENDERPATH_GL20:
6555 case RENDERPATH_D3D9:
6556 case RENDERPATH_D3D10:
6557 case RENDERPATH_D3D11:
6558 case RENDERPATH_SOFT:
6559 case RENDERPATH_GLES2:
6561 case RENDERPATH_GL11:
6562 case RENDERPATH_GL13:
6563 case RENDERPATH_GLES1:
6567 // set bloomwidth and bloomheight to the bloom resolution that will be
6568 // used (often less than the screen resolution for faster rendering)
6569 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6570 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6571 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6572 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6573 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6575 // calculate desired texture sizes
6576 if (vid.support.arb_texture_non_power_of_two)
6578 screentexturewidth = vid.width;
6579 screentextureheight = vid.height;
6580 bloomtexturewidth = r_fb.bloomwidth;
6581 bloomtextureheight = r_fb.bloomheight;
6585 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
6586 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
6587 for (bloomtexturewidth = 1;bloomtexturewidth < r_fb.bloomwidth ;bloomtexturewidth *= 2);
6588 for (bloomtextureheight = 1;bloomtextureheight < r_fb.bloomheight;bloomtextureheight *= 2);
6591 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))
6593 Cvar_SetValueQuick(&r_bloom, 0);
6594 Cvar_SetValueQuick(&r_motionblur, 0);
6595 Cvar_SetValueQuick(&r_damageblur, 0);
6598 if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6600 && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6602 && r_viewscale.value == 1.0f
6603 && !r_viewscale_fpsscaling.integer)
6604 screentexturewidth = screentextureheight = 0;
6605 if (!r_bloom.integer)
6606 bloomtexturewidth = bloomtextureheight = 0;
6608 // allocate textures as needed
6609 if (r_fb.screentexturewidth != screentexturewidth
6610 || r_fb.screentextureheight != screentextureheight
6611 || r_fb.bloomtexturewidth != bloomtexturewidth
6612 || r_fb.bloomtextureheight != bloomtextureheight
6613 || r_fb.textype != textype
6614 || useviewfbo != (r_fb.fbo != 0))
6616 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6618 if (r_fb.bloomtexture[i])
6619 R_FreeTexture(r_fb.bloomtexture[i]);
6620 r_fb.bloomtexture[i] = NULL;
6622 if (r_fb.bloomfbo[i])
6623 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6624 r_fb.bloomfbo[i] = 0;
6628 R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6631 if (r_fb.colortexture)
6632 R_FreeTexture(r_fb.colortexture);
6633 r_fb.colortexture = NULL;
6635 if (r_fb.depthtexture)
6636 R_FreeTexture(r_fb.depthtexture);
6637 r_fb.depthtexture = NULL;
6639 if (r_fb.ghosttexture)
6640 R_FreeTexture(r_fb.ghosttexture);
6641 r_fb.ghosttexture = NULL;
6643 r_fb.screentexturewidth = screentexturewidth;
6644 r_fb.screentextureheight = screentextureheight;
6645 r_fb.bloomtexturewidth = bloomtexturewidth;
6646 r_fb.bloomtextureheight = bloomtextureheight;
6647 r_fb.textype = textype;
6649 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6651 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6652 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);
6653 r_fb.ghosttexture_valid = false;
6654 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);
6657 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6658 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6659 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6663 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6665 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6667 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);
6669 r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6674 // bloom texture is a different resolution
6675 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6676 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6677 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6678 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6679 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6681 // set up a texcoord array for the full resolution screen image
6682 // (we have to keep this around to copy back during final render)
6683 r_fb.screentexcoord2f[0] = 0;
6684 r_fb.screentexcoord2f[1] = (float)viewheight / (float)r_fb.screentextureheight;
6685 r_fb.screentexcoord2f[2] = (float)viewwidth / (float)r_fb.screentexturewidth;
6686 r_fb.screentexcoord2f[3] = (float)viewheight / (float)r_fb.screentextureheight;
6687 r_fb.screentexcoord2f[4] = (float)viewwidth / (float)r_fb.screentexturewidth;
6688 r_fb.screentexcoord2f[5] = 0;
6689 r_fb.screentexcoord2f[6] = 0;
6690 r_fb.screentexcoord2f[7] = 0;
6694 for (i = 1;i < 8;i += 2)
6696 r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6700 // set up a texcoord array for the reduced resolution bloom image
6701 // (which will be additive blended over the screen image)
6702 r_fb.bloomtexcoord2f[0] = 0;
6703 r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6704 r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6705 r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6706 r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6707 r_fb.bloomtexcoord2f[5] = 0;
6708 r_fb.bloomtexcoord2f[6] = 0;
6709 r_fb.bloomtexcoord2f[7] = 0;
6711 switch(vid.renderpath)
6713 case RENDERPATH_GL11:
6714 case RENDERPATH_GL13:
6715 case RENDERPATH_GL20:
6716 case RENDERPATH_SOFT:
6717 case RENDERPATH_GLES1:
6718 case RENDERPATH_GLES2:
6720 case RENDERPATH_D3D9:
6721 case RENDERPATH_D3D10:
6722 case RENDERPATH_D3D11:
6723 for (i = 0;i < 4;i++)
6725 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6726 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6727 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6728 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6733 R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6736 r_refdef.view.clear = true;
6739 static void R_Bloom_MakeTexture(void)
6742 float xoffset, yoffset, r, brighten;
6744 float colorscale = r_bloom_colorscale.value;
6746 r_refdef.stats[r_stat_bloom]++;
6749 // this copy is unnecessary since it happens in R_BlendView already
6752 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);
6753 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6757 // scale down screen texture to the bloom texture size
6759 r_fb.bloomindex = 0;
6760 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6761 R_SetViewport(&r_fb.bloomviewport);
6762 GL_CullFace(GL_NONE);
6763 GL_DepthTest(false);
6764 GL_BlendFunc(GL_ONE, GL_ZERO);
6765 GL_Color(colorscale, colorscale, colorscale, 1);
6766 // 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...
6767 switch(vid.renderpath)
6769 case RENDERPATH_GL11:
6770 case RENDERPATH_GL13:
6771 case RENDERPATH_GL20:
6772 case RENDERPATH_GLES1:
6773 case RENDERPATH_GLES2:
6774 case RENDERPATH_SOFT:
6775 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6777 case RENDERPATH_D3D9:
6778 case RENDERPATH_D3D10:
6779 case RENDERPATH_D3D11:
6780 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6783 // TODO: do boxfilter scale-down in shader?
6784 R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6785 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6786 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6788 // we now have a properly scaled bloom image
6789 if (!r_fb.bloomfbo[r_fb.bloomindex])
6791 // copy it into the bloom texture
6792 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);
6793 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6796 // multiply bloom image by itself as many times as desired
6797 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6799 intex = r_fb.bloomtexture[r_fb.bloomindex];
6800 r_fb.bloomindex ^= 1;
6801 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6803 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6804 if (!r_fb.bloomfbo[r_fb.bloomindex])
6806 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6807 GL_Color(r,r,r,1); // apply fix factor
6812 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6813 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6814 GL_Color(1,1,1,1); // no fix factor supported here
6816 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6817 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6818 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6819 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6821 if (!r_fb.bloomfbo[r_fb.bloomindex])
6823 // copy the darkened image to a texture
6824 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);
6825 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6829 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6830 brighten = r_bloom_brighten.value;
6831 brighten = sqrt(brighten);
6833 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6835 for (dir = 0;dir < 2;dir++)
6837 intex = r_fb.bloomtexture[r_fb.bloomindex];
6838 r_fb.bloomindex ^= 1;
6839 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6840 // blend on at multiple vertical offsets to achieve a vertical blur
6841 // TODO: do offset blends using GLSL
6842 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6843 GL_BlendFunc(GL_ONE, GL_ZERO);
6844 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6845 for (x = -range;x <= range;x++)
6847 if (!dir){xoffset = 0;yoffset = x;}
6848 else {xoffset = x;yoffset = 0;}
6849 xoffset /= (float)r_fb.bloomtexturewidth;
6850 yoffset /= (float)r_fb.bloomtextureheight;
6851 // compute a texcoord array with the specified x and y offset
6852 r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6853 r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6854 r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6855 r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6856 r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6857 r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6858 r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6859 r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6860 // this r value looks like a 'dot' particle, fading sharply to
6861 // black at the edges
6862 // (probably not realistic but looks good enough)
6863 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6864 //r = brighten/(range*2+1);
6865 r = brighten / (range * 2 + 1);
6867 r *= (1 - x*x/(float)(range*range));
6868 GL_Color(r, r, r, 1);
6869 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6870 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6871 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6872 GL_BlendFunc(GL_ONE, GL_ONE);
6875 if (!r_fb.bloomfbo[r_fb.bloomindex])
6877 // copy the vertically or horizontally blurred bloom view to a texture
6878 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);
6879 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6884 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6886 dpuint64 permutation;
6887 float uservecs[4][4];
6889 R_EntityMatrix(&identitymatrix);
6891 switch (vid.renderpath)
6893 case RENDERPATH_GL20:
6894 case RENDERPATH_D3D9:
6895 case RENDERPATH_D3D10:
6896 case RENDERPATH_D3D11:
6897 case RENDERPATH_SOFT:
6898 case RENDERPATH_GLES2:
6900 (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6901 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6902 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6903 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6904 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6906 if (r_fb.colortexture)
6910 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);
6911 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6914 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6916 // declare variables
6917 float blur_factor, blur_mouseaccel, blur_velocity;
6918 static float blur_average;
6919 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6921 // set a goal for the factoring
6922 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6923 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6924 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6925 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6926 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6927 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6929 // from the goal, pick an averaged value between goal and last value
6930 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6931 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6933 // enforce minimum amount of blur
6934 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6936 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6938 // calculate values into a standard alpha
6939 cl.motionbluralpha = 1 - exp(-
6941 (r_motionblur.value * blur_factor / 80)
6943 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6946 max(0.0001, cl.time - cl.oldtime) // fps independent
6949 // randomization for the blur value to combat persistent ghosting
6950 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6951 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6954 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6955 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6957 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6958 GL_Color(1, 1, 1, cl.motionbluralpha);
6959 switch(vid.renderpath)
6961 case RENDERPATH_GL11:
6962 case RENDERPATH_GL13:
6963 case RENDERPATH_GL20:
6964 case RENDERPATH_GLES1:
6965 case RENDERPATH_GLES2:
6966 case RENDERPATH_SOFT:
6967 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6969 case RENDERPATH_D3D9:
6970 case RENDERPATH_D3D10:
6971 case RENDERPATH_D3D11:
6972 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6975 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6976 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6977 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6980 // updates old view angles for next pass
6981 VectorCopy(cl.viewangles, blur_oldangles);
6983 // copy view into the ghost texture
6984 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);
6985 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6986 r_fb.ghosttexture_valid = true;
6991 // no r_fb.colortexture means we're rendering to the real fb
6992 // we may still have to do view tint...
6993 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6995 // apply a color tint to the whole view
6996 R_ResetViewRendering2D(0, NULL, NULL);
6997 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6998 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6999 R_SetupShader_Generic_NoTexture(false, true);
7000 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7001 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7003 break; // no screen processing, no bloom, skip it
7006 if (r_fb.bloomtexture[0])
7008 // make the bloom texture
7009 R_Bloom_MakeTexture();
7012 #if _MSC_VER >= 1400
7013 #define sscanf sscanf_s
7015 memset(uservecs, 0, sizeof(uservecs));
7016 if (r_glsl_postprocess_uservec1_enable.integer)
7017 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
7018 if (r_glsl_postprocess_uservec2_enable.integer)
7019 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
7020 if (r_glsl_postprocess_uservec3_enable.integer)
7021 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
7022 if (r_glsl_postprocess_uservec4_enable.integer)
7023 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
7025 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
7026 GL_Color(1, 1, 1, 1);
7027 GL_BlendFunc(GL_ONE, GL_ZERO);
7029 switch(vid.renderpath)
7031 case RENDERPATH_GL20:
7032 case RENDERPATH_GLES2:
7033 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7034 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
7035 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_fb.colortexture);
7036 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_fb.bloomtexture[r_fb.bloomindex]);
7037 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
7038 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]);
7039 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7040 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]);
7041 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]);
7042 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]);
7043 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]);
7044 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
7045 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7046 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);
7048 case RENDERPATH_D3D9:
7050 // 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...
7051 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7052 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
7053 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
7054 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
7055 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7056 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7057 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7058 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7059 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7060 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7061 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7062 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
7063 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
7064 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7067 case RENDERPATH_D3D10:
7068 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7070 case RENDERPATH_D3D11:
7071 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7073 case RENDERPATH_SOFT:
7074 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
7075 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
7076 R_Mesh_TexBind(GL20TU_FIRST , r_fb.colortexture);
7077 R_Mesh_TexBind(GL20TU_SECOND , r_fb.bloomtexture[r_fb.bloomindex]);
7078 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
7079 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7080 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
7081 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
7082 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
7083 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
7084 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
7085 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
7086 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
7087 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
7092 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7093 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
7095 case RENDERPATH_GL11:
7096 case RENDERPATH_GL13:
7097 case RENDERPATH_GLES1:
7098 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
7100 // apply a color tint to the whole view
7101 R_ResetViewRendering2D(0, NULL, NULL);
7102 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
7103 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
7104 R_SetupShader_Generic_NoTexture(false, true);
7105 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7106 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
7112 matrix4x4_t r_waterscrollmatrix;
7114 void R_UpdateFog(void)
7117 if (gamemode == GAME_NEHAHRA)
7119 if (gl_fogenable.integer)
7121 r_refdef.oldgl_fogenable = true;
7122 r_refdef.fog_density = gl_fogdensity.value;
7123 r_refdef.fog_red = gl_fogred.value;
7124 r_refdef.fog_green = gl_foggreen.value;
7125 r_refdef.fog_blue = gl_fogblue.value;
7126 r_refdef.fog_alpha = 1;
7127 r_refdef.fog_start = 0;
7128 r_refdef.fog_end = gl_skyclip.value;
7129 r_refdef.fog_height = 1<<30;
7130 r_refdef.fog_fadedepth = 128;
7132 else if (r_refdef.oldgl_fogenable)
7134 r_refdef.oldgl_fogenable = false;
7135 r_refdef.fog_density = 0;
7136 r_refdef.fog_red = 0;
7137 r_refdef.fog_green = 0;
7138 r_refdef.fog_blue = 0;
7139 r_refdef.fog_alpha = 0;
7140 r_refdef.fog_start = 0;
7141 r_refdef.fog_end = 0;
7142 r_refdef.fog_height = 1<<30;
7143 r_refdef.fog_fadedepth = 128;
7148 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7149 r_refdef.fog_start = max(0, r_refdef.fog_start);
7150 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7152 if (r_refdef.fog_density && r_drawfog.integer)
7154 r_refdef.fogenabled = true;
7155 // this is the point where the fog reaches 0.9986 alpha, which we
7156 // consider a good enough cutoff point for the texture
7157 // (0.9986 * 256 == 255.6)
7158 if (r_fog_exp2.integer)
7159 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7161 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7162 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7163 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7164 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7165 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7166 R_BuildFogHeightTexture();
7167 // fog color was already set
7168 // update the fog texture
7169 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)
7170 R_BuildFogTexture();
7171 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7172 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7175 r_refdef.fogenabled = false;
7178 if (r_refdef.fog_density)
7180 r_refdef.fogcolor[0] = r_refdef.fog_red;
7181 r_refdef.fogcolor[1] = r_refdef.fog_green;
7182 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7184 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7185 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7186 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7187 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7191 VectorCopy(r_refdef.fogcolor, fogvec);
7192 // color.rgb *= ContrastBoost * SceneBrightness;
7193 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7194 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7195 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7196 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7201 void R_UpdateVariables(void)
7205 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7207 r_refdef.farclip = r_farclip_base.value;
7208 if (r_refdef.scene.worldmodel)
7209 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7210 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7212 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7213 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7214 r_refdef.polygonfactor = 0;
7215 r_refdef.polygonoffset = 0;
7216 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7217 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7219 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7220 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7221 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7222 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7223 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7224 if (FAKELIGHT_ENABLED)
7226 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7228 else if (r_refdef.scene.worldmodel)
7230 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7232 if (r_showsurfaces.integer)
7234 r_refdef.scene.rtworld = false;
7235 r_refdef.scene.rtworldshadows = false;
7236 r_refdef.scene.rtdlight = false;
7237 r_refdef.scene.rtdlightshadows = false;
7238 r_refdef.lightmapintensity = 0;
7241 r_gpuskeletal = false;
7242 switch(vid.renderpath)
7244 case RENDERPATH_GL20:
7245 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7246 case RENDERPATH_D3D9:
7247 case RENDERPATH_D3D10:
7248 case RENDERPATH_D3D11:
7249 case RENDERPATH_SOFT:
7250 case RENDERPATH_GLES2:
7251 if(v_glslgamma.integer && !vid_gammatables_trivial)
7253 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7255 // build GLSL gamma texture
7256 #define RAMPWIDTH 256
7257 unsigned short ramp[RAMPWIDTH * 3];
7258 unsigned char rampbgr[RAMPWIDTH][4];
7261 r_texture_gammaramps_serial = vid_gammatables_serial;
7263 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7264 for(i = 0; i < RAMPWIDTH; ++i)
7266 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7267 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7268 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7271 if (r_texture_gammaramps)
7273 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7277 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7283 // remove GLSL gamma texture
7286 case RENDERPATH_GL11:
7287 case RENDERPATH_GL13:
7288 case RENDERPATH_GLES1:
7293 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7294 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7300 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7301 if( scenetype != r_currentscenetype ) {
7302 // store the old scenetype
7303 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7304 r_currentscenetype = scenetype;
7305 // move in the new scene
7306 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7315 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7317 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7318 if( scenetype == r_currentscenetype ) {
7319 return &r_refdef.scene;
7321 return &r_scenes_store[ scenetype ];
7325 static int R_SortEntities_Compare(const void *ap, const void *bp)
7327 const entity_render_t *a = *(const entity_render_t **)ap;
7328 const entity_render_t *b = *(const entity_render_t **)bp;
7331 if(a->model < b->model)
7333 if(a->model > b->model)
7337 // TODO possibly calculate the REAL skinnum here first using
7339 if(a->skinnum < b->skinnum)
7341 if(a->skinnum > b->skinnum)
7344 // everything we compared is equal
7347 static void R_SortEntities(void)
7349 // below or equal 2 ents, sorting never gains anything
7350 if(r_refdef.scene.numentities <= 2)
7353 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7361 int dpsoftrast_test;
7362 extern cvar_t r_shadow_bouncegrid;
7363 void R_RenderView(void)
7365 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7367 rtexture_t *depthtexture;
7368 rtexture_t *colortexture;
7370 dpsoftrast_test = r_test.integer;
7372 if (r_timereport_active)
7373 R_TimeReport("start");
7374 r_textureframe++; // used only by R_GetCurrentTexture
7375 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7377 if(R_CompileShader_CheckStaticParms())
7380 if (!r_drawentities.integer)
7381 r_refdef.scene.numentities = 0;
7382 else if (r_sortentities.integer)
7385 R_AnimCache_ClearCache();
7387 /* adjust for stereo display */
7388 if(R_Stereo_Active())
7390 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);
7391 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7394 if (r_refdef.view.isoverlay)
7396 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7397 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7398 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7399 R_TimeReport("depthclear");
7401 r_refdef.view.showdebug = false;
7403 r_fb.water.enabled = false;
7404 r_fb.water.numwaterplanes = 0;
7406 R_RenderScene(0, NULL, NULL);
7408 r_refdef.view.matrix = originalmatrix;
7414 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7416 r_refdef.view.matrix = originalmatrix;
7420 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7422 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7423 // in sRGB fallback, behave similar to true sRGB: convert this
7424 // value from linear to sRGB
7425 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7427 R_RenderView_UpdateViewVectors();
7429 R_Shadow_UpdateWorldLightSelection();
7431 R_Bloom_StartFrame();
7433 // apply bloom brightness offset
7434 if(r_fb.bloomtexture[0])
7435 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7437 R_Water_StartFrame();
7439 // now we probably have an fbo to render into
7441 depthtexture = r_fb.depthtexture;
7442 colortexture = r_fb.colortexture;
7445 if (r_timereport_active)
7446 R_TimeReport("viewsetup");
7448 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7450 if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7452 R_ClearScreen(r_refdef.fogenabled);
7453 if (r_timereport_active)
7454 R_TimeReport("viewclear");
7456 r_refdef.view.clear = true;
7458 r_refdef.view.showdebug = true;
7461 if (r_timereport_active)
7462 R_TimeReport("visibility");
7464 R_AnimCache_CacheVisibleEntities();
7465 if (r_timereport_active)
7466 R_TimeReport("animcache");
7468 R_Shadow_UpdateBounceGridTexture();
7469 if (r_timereport_active && r_shadow_bouncegrid.integer)
7470 R_TimeReport("bouncegrid");
7472 r_fb.water.numwaterplanes = 0;
7473 if (r_fb.water.enabled)
7474 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7476 R_RenderScene(fbo, depthtexture, colortexture);
7477 r_fb.water.numwaterplanes = 0;
7479 R_BlendView(fbo, depthtexture, colortexture);
7480 if (r_timereport_active)
7481 R_TimeReport("blendview");
7483 GL_Scissor(0, 0, vid.width, vid.height);
7484 GL_ScissorTest(false);
7486 r_refdef.view.matrix = originalmatrix;
7491 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7493 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7495 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7496 if (r_timereport_active)
7497 R_TimeReport("waterworld");
7500 // don't let sound skip if going slow
7501 if (r_refdef.scene.extraupdate)
7504 R_DrawModelsAddWaterPlanes();
7505 if (r_timereport_active)
7506 R_TimeReport("watermodels");
7508 if (r_fb.water.numwaterplanes)
7510 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7511 if (r_timereport_active)
7512 R_TimeReport("waterscenes");
7516 extern cvar_t cl_locs_show;
7517 static void R_DrawLocs(void);
7518 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7519 static void R_DrawModelDecals(void);
7520 extern cvar_t cl_decals_newsystem;
7521 extern qboolean r_shadow_usingdeferredprepass;
7522 extern int r_shadow_shadowmapatlas_modelshadows_size;
7523 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7525 qboolean shadowmapping = false;
7527 if (r_timereport_active)
7528 R_TimeReport("beginscene");
7530 r_refdef.stats[r_stat_renders]++;
7534 // don't let sound skip if going slow
7535 if (r_refdef.scene.extraupdate)
7538 R_MeshQueue_BeginScene();
7542 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);
7544 if (r_timereport_active)
7545 R_TimeReport("skystartframe");
7547 if (cl.csqc_vidvars.drawworld)
7549 // don't let sound skip if going slow
7550 if (r_refdef.scene.extraupdate)
7553 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7555 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7556 if (r_timereport_active)
7557 R_TimeReport("worldsky");
7560 if (R_DrawBrushModelsSky() && r_timereport_active)
7561 R_TimeReport("bmodelsky");
7563 if (skyrendermasked && skyrenderlater)
7565 // we have to force off the water clipping plane while rendering sky
7566 R_SetupView(false, fbo, depthtexture, colortexture);
7568 R_SetupView(true, fbo, depthtexture, colortexture);
7569 if (r_timereport_active)
7570 R_TimeReport("sky");
7574 R_Shadow_PrepareModelShadows();
7575 R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7576 if (r_timereport_active)
7577 R_TimeReport("preparelights");
7579 // render all the shadowmaps that will be used for this view
7580 shadowmapping = R_Shadow_ShadowMappingEnabled();
7581 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7583 R_Shadow_DrawShadowMaps();
7584 if (r_timereport_active)
7585 R_TimeReport("shadowmaps");
7588 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7589 if (r_shadow_usingdeferredprepass)
7590 R_Shadow_DrawPrepass();
7592 // now we begin the forward pass of the view render
7593 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7595 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7596 if (r_timereport_active)
7597 R_TimeReport("worlddepth");
7599 if (r_depthfirst.integer >= 2)
7601 R_DrawModelsDepth();
7602 if (r_timereport_active)
7603 R_TimeReport("modeldepth");
7606 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7608 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7609 if (r_timereport_active)
7610 R_TimeReport("world");
7613 // don't let sound skip if going slow
7614 if (r_refdef.scene.extraupdate)
7618 if (r_timereport_active)
7619 R_TimeReport("models");
7621 // don't let sound skip if going slow
7622 if (r_refdef.scene.extraupdate)
7625 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7627 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7628 R_Shadow_DrawModelShadows();
7629 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7630 // don't let sound skip if going slow
7631 if (r_refdef.scene.extraupdate)
7635 if (!r_shadow_usingdeferredprepass)
7637 R_Shadow_DrawLights();
7638 if (r_timereport_active)
7639 R_TimeReport("rtlights");
7642 // don't let sound skip if going slow
7643 if (r_refdef.scene.extraupdate)
7646 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7648 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7649 R_Shadow_DrawModelShadows();
7650 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7651 // don't let sound skip if going slow
7652 if (r_refdef.scene.extraupdate)
7656 if (cl.csqc_vidvars.drawworld)
7658 if (cl_decals_newsystem.integer)
7660 R_DrawModelDecals();
7661 if (r_timereport_active)
7662 R_TimeReport("modeldecals");
7667 if (r_timereport_active)
7668 R_TimeReport("decals");
7672 if (r_timereport_active)
7673 R_TimeReport("particles");
7676 if (r_timereport_active)
7677 R_TimeReport("explosions");
7681 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7683 if (r_refdef.view.showdebug)
7685 if (cl_locs_show.integer)
7688 if (r_timereport_active)
7689 R_TimeReport("showlocs");
7692 if (r_drawportals.integer)
7695 if (r_timereport_active)
7696 R_TimeReport("portals");
7699 if (r_showbboxes_client.value > 0)
7701 R_DrawEntityBBoxes(CLVM_prog);
7702 if (r_timereport_active)
7703 R_TimeReport("clbboxes");
7705 if (r_showbboxes.value > 0)
7707 R_DrawEntityBBoxes(SVVM_prog);
7708 if (r_timereport_active)
7709 R_TimeReport("svbboxes");
7713 if (r_transparent.integer)
7715 R_MeshQueue_RenderTransparent();
7716 if (r_timereport_active)
7717 R_TimeReport("drawtrans");
7720 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))
7722 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7723 if (r_timereport_active)
7724 R_TimeReport("worlddebug");
7725 R_DrawModelsDebug();
7726 if (r_timereport_active)
7727 R_TimeReport("modeldebug");
7730 if (cl.csqc_vidvars.drawworld)
7732 R_Shadow_DrawCoronas();
7733 if (r_timereport_active)
7734 R_TimeReport("coronas");
7739 GL_DepthTest(false);
7740 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7741 GL_Color(1, 1, 1, 1);
7742 qglBegin(GL_POLYGON);
7743 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7744 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7745 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7746 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7748 qglBegin(GL_POLYGON);
7749 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]);
7750 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]);
7751 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]);
7752 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]);
7754 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7758 // don't let sound skip if going slow
7759 if (r_refdef.scene.extraupdate)
7763 static const unsigned short bboxelements[36] =
7773 #define BBOXEDGES 13
7774 static const float bboxedges[BBOXEDGES][6] =
7777 { 0, 0, 0, 1, 1, 1 },
7779 { 0, 0, 0, 0, 1, 0 },
7780 { 0, 0, 0, 1, 0, 0 },
7781 { 0, 1, 0, 1, 1, 0 },
7782 { 1, 0, 0, 1, 1, 0 },
7784 { 0, 0, 1, 0, 1, 1 },
7785 { 0, 0, 1, 1, 0, 1 },
7786 { 0, 1, 1, 1, 1, 1 },
7787 { 1, 0, 1, 1, 1, 1 },
7789 { 0, 0, 0, 0, 0, 1 },
7790 { 1, 0, 0, 1, 0, 1 },
7791 { 0, 1, 0, 0, 1, 1 },
7792 { 1, 1, 0, 1, 1, 1 },
7795 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7797 int numvertices = BBOXEDGES * 8;
7798 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7799 int numtriangles = BBOXEDGES * 12;
7800 unsigned short elements[BBOXEDGES * 36];
7802 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7804 RSurf_ActiveWorldEntity();
7806 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7807 GL_DepthMask(false);
7808 GL_DepthRange(0, 1);
7809 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7811 for (edge = 0; edge < BBOXEDGES; edge++)
7813 for (i = 0; i < 3; i++)
7815 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7816 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7818 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7819 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7820 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7821 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7822 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7823 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7824 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7825 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7826 for (i = 0; i < 36; i++)
7827 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7829 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7830 if (r_refdef.fogenabled)
7832 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7834 f1 = RSurf_FogVertex(v);
7836 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7837 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7838 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7841 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7842 R_Mesh_ResetTextureState();
7843 R_SetupShader_Generic_NoTexture(false, false);
7844 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7847 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7849 // hacky overloading of the parameters
7850 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7853 prvm_edict_t *edict;
7855 GL_CullFace(GL_NONE);
7856 R_SetupShader_Generic_NoTexture(false, false);
7858 for (i = 0;i < numsurfaces;i++)
7860 edict = PRVM_EDICT_NUM(surfacelist[i]);
7861 switch ((int)PRVM_serveredictfloat(edict, solid))
7863 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7864 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7865 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7866 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7867 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7868 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7869 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7871 if (prog == CLVM_prog)
7872 color[3] *= r_showbboxes_client.value;
7874 color[3] *= r_showbboxes.value;
7875 color[3] = bound(0, color[3], 1);
7876 GL_DepthTest(!r_showdisabledepthtest.integer);
7877 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7881 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7884 prvm_edict_t *edict;
7890 for (i = 0; i < prog->num_edicts; i++)
7892 edict = PRVM_EDICT_NUM(i);
7893 if (edict->priv.server->free)
7895 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7896 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7898 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7900 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7901 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7905 static const int nomodelelement3i[24] =
7917 static const unsigned short nomodelelement3s[24] =
7929 static const float nomodelvertex3f[6*3] =
7939 static const float nomodelcolor4f[6*4] =
7941 0.0f, 0.0f, 0.5f, 1.0f,
7942 0.0f, 0.0f, 0.5f, 1.0f,
7943 0.0f, 0.5f, 0.0f, 1.0f,
7944 0.0f, 0.5f, 0.0f, 1.0f,
7945 0.5f, 0.0f, 0.0f, 1.0f,
7946 0.5f, 0.0f, 0.0f, 1.0f
7949 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7955 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);
7957 // this is only called once per entity so numsurfaces is always 1, and
7958 // surfacelist is always {0}, so this code does not handle batches
7960 if (rsurface.ent_flags & RENDER_ADDITIVE)
7962 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7963 GL_DepthMask(false);
7965 else if (rsurface.colormod[3] < 1)
7967 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7968 GL_DepthMask(false);
7972 GL_BlendFunc(GL_ONE, GL_ZERO);
7975 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7976 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7977 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7978 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7979 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7980 for (i = 0, c = color4f;i < 6;i++, c += 4)
7982 c[0] *= rsurface.colormod[0];
7983 c[1] *= rsurface.colormod[1];
7984 c[2] *= rsurface.colormod[2];
7985 c[3] *= rsurface.colormod[3];
7987 if (r_refdef.fogenabled)
7989 for (i = 0, c = color4f;i < 6;i++, c += 4)
7991 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7993 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7994 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7995 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7998 // R_Mesh_ResetTextureState();
7999 R_SetupShader_Generic_NoTexture(false, false);
8000 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
8001 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
8004 void R_DrawNoModel(entity_render_t *ent)
8007 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8008 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
8009 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
8011 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
8014 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
8016 vec3_t right1, right2, diff, normal;
8018 VectorSubtract (org2, org1, normal);
8020 // calculate 'right' vector for start
8021 VectorSubtract (r_refdef.view.origin, org1, diff);
8022 CrossProduct (normal, diff, right1);
8023 VectorNormalize (right1);
8025 // calculate 'right' vector for end
8026 VectorSubtract (r_refdef.view.origin, org2, diff);
8027 CrossProduct (normal, diff, right2);
8028 VectorNormalize (right2);
8030 vert[ 0] = org1[0] + width * right1[0];
8031 vert[ 1] = org1[1] + width * right1[1];
8032 vert[ 2] = org1[2] + width * right1[2];
8033 vert[ 3] = org1[0] - width * right1[0];
8034 vert[ 4] = org1[1] - width * right1[1];
8035 vert[ 5] = org1[2] - width * right1[2];
8036 vert[ 6] = org2[0] - width * right2[0];
8037 vert[ 7] = org2[1] - width * right2[1];
8038 vert[ 8] = org2[2] - width * right2[2];
8039 vert[ 9] = org2[0] + width * right2[0];
8040 vert[10] = org2[1] + width * right2[1];
8041 vert[11] = org2[2] + width * right2[2];
8044 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)
8046 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
8047 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
8048 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
8049 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
8050 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
8051 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
8052 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
8053 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
8054 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
8055 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
8056 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
8057 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
8060 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
8065 VectorSet(v, x, y, z);
8066 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
8067 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
8069 if (i == mesh->numvertices)
8071 if (mesh->numvertices < mesh->maxvertices)
8073 VectorCopy(v, vertex3f);
8074 mesh->numvertices++;
8076 return mesh->numvertices;
8082 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
8086 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8087 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
8088 e = mesh->element3i + mesh->numtriangles * 3;
8089 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
8091 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
8092 if (mesh->numtriangles < mesh->maxtriangles)
8097 mesh->numtriangles++;
8099 element[1] = element[2];
8103 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
8107 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8108 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
8109 e = mesh->element3i + mesh->numtriangles * 3;
8110 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
8112 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
8113 if (mesh->numtriangles < mesh->maxtriangles)
8118 mesh->numtriangles++;
8120 element[1] = element[2];
8124 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
8125 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
8127 int planenum, planenum2;
8130 mplane_t *plane, *plane2;
8132 double temppoints[2][256*3];
8133 // figure out how large a bounding box we need to properly compute this brush
8135 for (w = 0;w < numplanes;w++)
8136 maxdist = max(maxdist, fabs(planes[w].dist));
8137 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
8138 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
8139 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
8143 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
8144 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
8146 if (planenum2 == planenum)
8148 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);
8151 if (tempnumpoints < 3)
8153 // generate elements forming a triangle fan for this polygon
8154 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
8158 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)
8160 texturelayer_t *layer;
8161 layer = t->currentlayers + t->currentnumlayers++;
8163 layer->depthmask = depthmask;
8164 layer->blendfunc1 = blendfunc1;
8165 layer->blendfunc2 = blendfunc2;
8166 layer->texture = texture;
8167 layer->texmatrix = *matrix;
8168 layer->color[0] = r;
8169 layer->color[1] = g;
8170 layer->color[2] = b;
8171 layer->color[3] = a;
8174 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
8176 if(parms[0] == 0 && parms[1] == 0)
8178 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8179 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8184 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8187 index = parms[2] + rsurface.shadertime * parms[3];
8188 index -= floor(index);
8189 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8192 case Q3WAVEFUNC_NONE:
8193 case Q3WAVEFUNC_NOISE:
8194 case Q3WAVEFUNC_COUNT:
8197 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8198 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8199 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8200 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8201 case Q3WAVEFUNC_TRIANGLE:
8203 f = index - floor(index);
8216 f = parms[0] + parms[1] * f;
8217 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8218 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8222 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8229 matrix4x4_t matrix, temp;
8230 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8231 // it's better to have one huge fixup every 9 hours than gradual
8232 // degradation over time which looks consistently bad after many hours.
8234 // tcmod scroll in particular suffers from this degradation which can't be
8235 // effectively worked around even with floor() tricks because we don't
8236 // know if tcmod scroll is the last tcmod being applied, and for clampmap
8237 // a workaround involving floor() would be incorrect anyway...
8238 shadertime = rsurface.shadertime;
8239 if (shadertime >= 32768.0f)
8240 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8241 switch(tcmod->tcmod)
8245 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8246 matrix = r_waterscrollmatrix;
8248 matrix = identitymatrix;
8250 case Q3TCMOD_ENTITYTRANSLATE:
8251 // this is used in Q3 to allow the gamecode to control texcoord
8252 // scrolling on the entity, which is not supported in darkplaces yet.
8253 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8255 case Q3TCMOD_ROTATE:
8256 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8257 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8258 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8261 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8263 case Q3TCMOD_SCROLL:
8264 // this particular tcmod is a "bug for bug" compatible one with regards to
8265 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8266 // specifically did the wrapping and so we must mimic that...
8267 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8268 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8269 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8271 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8272 w = (int) tcmod->parms[0];
8273 h = (int) tcmod->parms[1];
8274 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8276 idx = (int) floor(f * w * h);
8277 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8279 case Q3TCMOD_STRETCH:
8280 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8281 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8283 case Q3TCMOD_TRANSFORM:
8284 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
8285 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
8286 VectorSet(tcmat + 6, 0 , 0 , 1);
8287 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
8288 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8290 case Q3TCMOD_TURBULENT:
8291 // this is handled in the RSurf_PrepareVertices function
8292 matrix = identitymatrix;
8296 Matrix4x4_Concat(texmatrix, &matrix, &temp);
8299 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8301 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8302 char name[MAX_QPATH];
8303 skinframe_t *skinframe;
8304 unsigned char pixels[296*194];
8305 strlcpy(cache->name, skinname, sizeof(cache->name));
8306 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8307 if (developer_loading.integer)
8308 Con_Printf("loading %s\n", name);
8309 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8310 if (!skinframe || !skinframe->base)
8313 fs_offset_t filesize;
8315 f = FS_LoadFile(name, tempmempool, true, &filesize);
8318 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8319 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8323 cache->skinframe = skinframe;
8326 texture_t *R_GetCurrentTexture(texture_t *t)
8329 const entity_render_t *ent = rsurface.entity;
8330 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8331 q3shaderinfo_layer_tcmod_t *tcmod;
8333 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8334 return t->currentframe;
8335 t->update_lastrenderframe = r_textureframe;
8336 t->update_lastrenderentity = (void *)ent;
8338 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8339 t->camera_entity = ent->entitynumber;
8341 t->camera_entity = 0;
8343 // switch to an alternate material if this is a q1bsp animated material
8345 texture_t *texture = t;
8346 int s = rsurface.ent_skinnum;
8347 if ((unsigned int)s >= (unsigned int)model->numskins)
8349 if (model->skinscenes)
8351 if (model->skinscenes[s].framecount > 1)
8352 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8354 s = model->skinscenes[s].firstframe;
8357 t = t + s * model->num_surfaces;
8360 // use an alternate animation if the entity's frame is not 0,
8361 // and only if the texture has an alternate animation
8362 if (t->animated == 2) // q2bsp
8363 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8364 else if (rsurface.ent_alttextures && t->anim_total[1])
8365 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8367 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8369 texture->currentframe = t;
8372 // update currentskinframe to be a qw skin or animation frame
8373 if (rsurface.ent_qwskin >= 0)
8375 i = rsurface.ent_qwskin;
8376 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8378 r_qwskincache_size = cl.maxclients;
8380 Mem_Free(r_qwskincache);
8381 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8383 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8384 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8385 t->currentskinframe = r_qwskincache[i].skinframe;
8386 if (t->materialshaderpass && t->currentskinframe == NULL)
8387 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8389 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
8390 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
8391 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
8392 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
8394 t->currentmaterialflags = t->basematerialflags;
8395 t->currentalpha = rsurface.colormod[3] * t->basealpha;
8396 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8397 t->currentalpha *= r_wateralpha.value;
8398 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8399 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8400 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8401 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8402 if (!(rsurface.ent_flags & RENDER_LIGHT))
8403 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8404 else if (FAKELIGHT_ENABLED)
8406 // no modellight if using fakelight for the map
8408 else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8410 // pick a model lighting mode
8411 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8412 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8414 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8416 if (rsurface.ent_flags & RENDER_ADDITIVE)
8417 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8418 else if (t->currentalpha < 1)
8419 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8420 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8421 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8422 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8423 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8424 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8425 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8426 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8427 if (t->backgroundshaderpass)
8428 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8429 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8431 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8432 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8435 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8436 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8438 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8439 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8441 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8442 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8444 // there is no tcmod
8445 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8447 t->currenttexmatrix = r_waterscrollmatrix;
8448 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8450 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8452 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8453 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8456 if (t->materialshaderpass)
8457 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8458 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8460 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8461 if (t->currentskinframe->qpixels)
8462 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8463 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8464 if (!t->basetexture)
8465 t->basetexture = r_texture_notexture;
8466 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8467 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8468 t->nmaptexture = t->currentskinframe->nmap;
8469 if (!t->nmaptexture)
8470 t->nmaptexture = r_texture_blanknormalmap;
8471 t->glosstexture = r_texture_black;
8472 t->glowtexture = t->currentskinframe->glow;
8473 t->fogtexture = t->currentskinframe->fog;
8474 t->reflectmasktexture = t->currentskinframe->reflect;
8475 if (t->backgroundshaderpass)
8477 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8478 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8479 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8480 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8481 t->backgroundglosstexture = r_texture_black;
8482 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8483 if (!t->backgroundnmaptexture)
8484 t->backgroundnmaptexture = r_texture_blanknormalmap;
8485 // make sure that if glow is going to be used, both textures are not NULL
8486 if (!t->backgroundglowtexture && t->glowtexture)
8487 t->backgroundglowtexture = r_texture_black;
8488 if (!t->glowtexture && t->backgroundglowtexture)
8489 t->glowtexture = r_texture_black;
8493 t->backgroundbasetexture = r_texture_white;
8494 t->backgroundnmaptexture = r_texture_blanknormalmap;
8495 t->backgroundglosstexture = r_texture_black;
8496 t->backgroundglowtexture = NULL;
8498 t->specularpower = r_shadow_glossexponent.value;
8499 // TODO: store reference values for these in the texture?
8500 t->specularscale = 0;
8501 if (r_shadow_gloss.integer > 0)
8503 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8505 if (r_shadow_glossintensity.value > 0)
8507 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8508 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8509 t->specularscale = r_shadow_glossintensity.value;
8512 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8514 t->glosstexture = r_texture_white;
8515 t->backgroundglosstexture = r_texture_white;
8516 t->specularscale = r_shadow_gloss2intensity.value;
8517 t->specularpower = r_shadow_gloss2exponent.value;
8520 t->specularscale *= t->specularscalemod;
8521 t->specularpower *= t->specularpowermod;
8522 t->rtlightambient = 0;
8524 // lightmaps mode looks bad with dlights using actual texturing, so turn
8525 // off the colormap and glossmap, but leave the normalmap on as it still
8526 // accurately represents the shading involved
8527 if (gl_lightmaps.integer)
8529 t->basetexture = r_texture_grey128;
8530 t->pantstexture = r_texture_black;
8531 t->shirttexture = r_texture_black;
8532 if (gl_lightmaps.integer < 2)
8533 t->nmaptexture = r_texture_blanknormalmap;
8534 t->glosstexture = r_texture_black;
8535 t->glowtexture = NULL;
8536 t->fogtexture = NULL;
8537 t->reflectmasktexture = NULL;
8538 t->backgroundbasetexture = NULL;
8539 if (gl_lightmaps.integer < 2)
8540 t->backgroundnmaptexture = r_texture_blanknormalmap;
8541 t->backgroundglosstexture = r_texture_black;
8542 t->backgroundglowtexture = NULL;
8543 t->specularscale = 0;
8544 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8547 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8548 VectorClear(t->dlightcolor);
8549 t->currentnumlayers = 0;
8550 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8552 int blendfunc1, blendfunc2;
8554 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8556 blendfunc1 = GL_SRC_ALPHA;
8557 blendfunc2 = GL_ONE;
8559 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8561 blendfunc1 = GL_SRC_ALPHA;
8562 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8564 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8566 blendfunc1 = t->customblendfunc[0];
8567 blendfunc2 = t->customblendfunc[1];
8571 blendfunc1 = GL_ONE;
8572 blendfunc2 = GL_ZERO;
8574 // don't colormod evilblend textures
8575 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8576 VectorSet(t->lightmapcolor, 1, 1, 1);
8577 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8578 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8580 // fullbright is not affected by r_refdef.lightmapintensity
8581 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8582 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8583 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8584 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8585 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8589 vec3_t ambientcolor;
8591 // set the color tint used for lights affecting this surface
8592 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8594 // q3bsp has no lightmap updates, so the lightstylevalue that
8595 // would normally be baked into the lightmap must be
8596 // applied to the color
8597 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8598 if (model->type == mod_brushq3)
8599 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8600 colorscale *= r_refdef.lightmapintensity;
8601 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8602 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8603 // basic lit geometry
8604 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8605 // add pants/shirt if needed
8606 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8607 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8608 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8609 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8610 // now add ambient passes if needed
8611 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8613 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8614 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8615 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8616 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8617 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8620 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8621 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8622 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8624 // if this is opaque use alpha blend which will darken the earlier
8627 // if this is an alpha blended material, all the earlier passes
8628 // were darkened by fog already, so we only need to add the fog
8629 // color ontop through the fog mask texture
8631 // if this is an additive blended material, all the earlier passes
8632 // were darkened by fog already, and we should not add fog color
8633 // (because the background was not darkened, there is no fog color
8634 // that was lost behind it).
8635 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8642 rsurfacestate_t rsurface;
8644 void RSurf_ActiveWorldEntity(void)
8646 dp_model_t *model = r_refdef.scene.worldmodel;
8647 //if (rsurface.entity == r_refdef.scene.worldentity)
8649 rsurface.entity = r_refdef.scene.worldentity;
8650 rsurface.skeleton = NULL;
8651 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8652 rsurface.ent_skinnum = 0;
8653 rsurface.ent_qwskin = -1;
8654 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8655 rsurface.shadertime = r_refdef.scene.time;
8656 rsurface.matrix = identitymatrix;
8657 rsurface.inversematrix = identitymatrix;
8658 rsurface.matrixscale = 1;
8659 rsurface.inversematrixscale = 1;
8660 R_EntityMatrix(&identitymatrix);
8661 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8662 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8663 rsurface.fograngerecip = r_refdef.fograngerecip;
8664 rsurface.fogheightfade = r_refdef.fogheightfade;
8665 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8666 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8667 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8669 R_GetDirectedFullbright(rsurface.modellight_ambient, rsurface.modellight_diffuse, rsurface.modellight_lightdir);
8670 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8674 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8675 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8676 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8678 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8679 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8680 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8681 rsurface.colormod[3] = 1;
8682 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8683 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8684 rsurface.frameblend[0].lerp = 1;
8685 rsurface.ent_alttextures = false;
8686 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8687 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8688 rsurface.entityskeletaltransform3x4 = NULL;
8689 rsurface.entityskeletaltransform3x4buffer = NULL;
8690 rsurface.entityskeletaltransform3x4offset = 0;
8691 rsurface.entityskeletaltransform3x4size = 0;;
8692 rsurface.entityskeletalnumtransforms = 0;
8693 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8694 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8695 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8696 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8697 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8698 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8699 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8700 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8701 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8702 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8703 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8704 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8705 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8706 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8707 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8708 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8709 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8710 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8711 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8712 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8713 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8714 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8715 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8716 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8717 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8718 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8719 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8720 rsurface.modelelement3i = model->surfmesh.data_element3i;
8721 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8722 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8723 rsurface.modelelement3s = model->surfmesh.data_element3s;
8724 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8725 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8726 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8727 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8728 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8729 rsurface.modelsurfaces = model->data_surfaces;
8730 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8731 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8732 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8733 rsurface.modelgeneratedvertex = false;
8734 rsurface.batchgeneratedvertex = false;
8735 rsurface.batchfirstvertex = 0;
8736 rsurface.batchnumvertices = 0;
8737 rsurface.batchfirsttriangle = 0;
8738 rsurface.batchnumtriangles = 0;
8739 rsurface.batchvertex3f = NULL;
8740 rsurface.batchvertex3f_vertexbuffer = NULL;
8741 rsurface.batchvertex3f_bufferoffset = 0;
8742 rsurface.batchsvector3f = NULL;
8743 rsurface.batchsvector3f_vertexbuffer = NULL;
8744 rsurface.batchsvector3f_bufferoffset = 0;
8745 rsurface.batchtvector3f = NULL;
8746 rsurface.batchtvector3f_vertexbuffer = NULL;
8747 rsurface.batchtvector3f_bufferoffset = 0;
8748 rsurface.batchnormal3f = NULL;
8749 rsurface.batchnormal3f_vertexbuffer = NULL;
8750 rsurface.batchnormal3f_bufferoffset = 0;
8751 rsurface.batchlightmapcolor4f = NULL;
8752 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8753 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8754 rsurface.batchtexcoordtexture2f = NULL;
8755 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8756 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8757 rsurface.batchtexcoordlightmap2f = NULL;
8758 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8759 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8760 rsurface.batchskeletalindex4ub = NULL;
8761 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8762 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8763 rsurface.batchskeletalweight4ub = NULL;
8764 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8765 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8766 rsurface.batchvertexmesh = NULL;
8767 rsurface.batchvertexmesh_vertexbuffer = NULL;
8768 rsurface.batchvertexmesh_bufferoffset = 0;
8769 rsurface.batchelement3i = NULL;
8770 rsurface.batchelement3i_indexbuffer = NULL;
8771 rsurface.batchelement3i_bufferoffset = 0;
8772 rsurface.batchelement3s = NULL;
8773 rsurface.batchelement3s_indexbuffer = NULL;
8774 rsurface.batchelement3s_bufferoffset = 0;
8775 rsurface.passcolor4f = NULL;
8776 rsurface.passcolor4f_vertexbuffer = NULL;
8777 rsurface.passcolor4f_bufferoffset = 0;
8778 rsurface.forcecurrenttextureupdate = false;
8781 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8783 dp_model_t *model = ent->model;
8784 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8786 rsurface.entity = (entity_render_t *)ent;
8787 rsurface.skeleton = ent->skeleton;
8788 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8789 rsurface.ent_skinnum = ent->skinnum;
8790 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;
8791 rsurface.ent_flags = ent->flags;
8792 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8794 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8796 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8797 rsurface.matrix = ent->matrix;
8798 rsurface.inversematrix = ent->inversematrix;
8799 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8800 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8801 R_EntityMatrix(&rsurface.matrix);
8802 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8803 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8804 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8805 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8806 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8807 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8808 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8809 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8810 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8811 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8812 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8813 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8814 rsurface.colormod[3] = ent->alpha;
8815 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8816 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8817 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8818 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8819 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8820 if (ent->model->brush.submodel && !prepass)
8822 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8823 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8825 // if the animcache code decided it should use the shader path, skip the deform step
8826 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8827 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8828 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8829 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8830 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8831 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8833 if (ent->animcache_vertex3f)
8835 r_refdef.stats[r_stat_batch_entitycache_count]++;
8836 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8837 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8838 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8839 rsurface.modelvertex3f = ent->animcache_vertex3f;
8840 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8841 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8842 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8843 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8844 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8845 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8846 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8847 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8848 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8849 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8850 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8851 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8852 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8853 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8855 else if (wanttangents)
8857 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8858 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8859 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8860 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8861 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8862 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8863 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8864 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8865 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8866 rsurface.modelvertexmesh = NULL;
8867 rsurface.modelvertexmesh_vertexbuffer = NULL;
8868 rsurface.modelvertexmesh_bufferoffset = 0;
8869 rsurface.modelvertex3f_vertexbuffer = NULL;
8870 rsurface.modelvertex3f_bufferoffset = 0;
8871 rsurface.modelvertex3f_vertexbuffer = 0;
8872 rsurface.modelvertex3f_bufferoffset = 0;
8873 rsurface.modelsvector3f_vertexbuffer = 0;
8874 rsurface.modelsvector3f_bufferoffset = 0;
8875 rsurface.modeltvector3f_vertexbuffer = 0;
8876 rsurface.modeltvector3f_bufferoffset = 0;
8877 rsurface.modelnormal3f_vertexbuffer = 0;
8878 rsurface.modelnormal3f_bufferoffset = 0;
8880 else if (wantnormals)
8882 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8883 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8884 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8885 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8886 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8887 rsurface.modelsvector3f = NULL;
8888 rsurface.modeltvector3f = NULL;
8889 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8890 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8891 rsurface.modelvertexmesh = NULL;
8892 rsurface.modelvertexmesh_vertexbuffer = NULL;
8893 rsurface.modelvertexmesh_bufferoffset = 0;
8894 rsurface.modelvertex3f_vertexbuffer = NULL;
8895 rsurface.modelvertex3f_bufferoffset = 0;
8896 rsurface.modelvertex3f_vertexbuffer = 0;
8897 rsurface.modelvertex3f_bufferoffset = 0;
8898 rsurface.modelsvector3f_vertexbuffer = 0;
8899 rsurface.modelsvector3f_bufferoffset = 0;
8900 rsurface.modeltvector3f_vertexbuffer = 0;
8901 rsurface.modeltvector3f_bufferoffset = 0;
8902 rsurface.modelnormal3f_vertexbuffer = 0;
8903 rsurface.modelnormal3f_bufferoffset = 0;
8907 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8908 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8909 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8910 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8911 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8912 rsurface.modelsvector3f = NULL;
8913 rsurface.modeltvector3f = NULL;
8914 rsurface.modelnormal3f = NULL;
8915 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8916 rsurface.modelvertexmesh = NULL;
8917 rsurface.modelvertexmesh_vertexbuffer = NULL;
8918 rsurface.modelvertexmesh_bufferoffset = 0;
8919 rsurface.modelvertex3f_vertexbuffer = NULL;
8920 rsurface.modelvertex3f_bufferoffset = 0;
8921 rsurface.modelvertex3f_vertexbuffer = 0;
8922 rsurface.modelvertex3f_bufferoffset = 0;
8923 rsurface.modelsvector3f_vertexbuffer = 0;
8924 rsurface.modelsvector3f_bufferoffset = 0;
8925 rsurface.modeltvector3f_vertexbuffer = 0;
8926 rsurface.modeltvector3f_bufferoffset = 0;
8927 rsurface.modelnormal3f_vertexbuffer = 0;
8928 rsurface.modelnormal3f_bufferoffset = 0;
8930 rsurface.modelgeneratedvertex = true;
8934 if (rsurface.entityskeletaltransform3x4)
8936 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8937 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8938 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8939 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8943 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8944 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8945 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8946 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8948 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8949 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8950 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8951 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8952 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8953 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8954 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8955 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8956 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8957 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8958 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8959 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8960 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8961 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8962 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8963 rsurface.modelgeneratedvertex = false;
8965 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8966 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8967 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8968 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8969 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8970 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8971 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8972 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8973 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8974 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8975 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8976 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8977 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8978 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8979 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8980 rsurface.modelelement3i = model->surfmesh.data_element3i;
8981 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8982 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8983 rsurface.modelelement3s = model->surfmesh.data_element3s;
8984 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8985 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8986 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8987 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8988 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8989 rsurface.modelsurfaces = model->data_surfaces;
8990 rsurface.batchgeneratedvertex = false;
8991 rsurface.batchfirstvertex = 0;
8992 rsurface.batchnumvertices = 0;
8993 rsurface.batchfirsttriangle = 0;
8994 rsurface.batchnumtriangles = 0;
8995 rsurface.batchvertex3f = NULL;
8996 rsurface.batchvertex3f_vertexbuffer = NULL;
8997 rsurface.batchvertex3f_bufferoffset = 0;
8998 rsurface.batchsvector3f = NULL;
8999 rsurface.batchsvector3f_vertexbuffer = NULL;
9000 rsurface.batchsvector3f_bufferoffset = 0;
9001 rsurface.batchtvector3f = NULL;
9002 rsurface.batchtvector3f_vertexbuffer = NULL;
9003 rsurface.batchtvector3f_bufferoffset = 0;
9004 rsurface.batchnormal3f = NULL;
9005 rsurface.batchnormal3f_vertexbuffer = NULL;
9006 rsurface.batchnormal3f_bufferoffset = 0;
9007 rsurface.batchlightmapcolor4f = NULL;
9008 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9009 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9010 rsurface.batchtexcoordtexture2f = NULL;
9011 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9012 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9013 rsurface.batchtexcoordlightmap2f = NULL;
9014 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9015 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9016 rsurface.batchskeletalindex4ub = NULL;
9017 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9018 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9019 rsurface.batchskeletalweight4ub = NULL;
9020 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9021 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9022 rsurface.batchvertexmesh = NULL;
9023 rsurface.batchvertexmesh_vertexbuffer = NULL;
9024 rsurface.batchvertexmesh_bufferoffset = 0;
9025 rsurface.batchelement3i = NULL;
9026 rsurface.batchelement3i_indexbuffer = NULL;
9027 rsurface.batchelement3i_bufferoffset = 0;
9028 rsurface.batchelement3s = NULL;
9029 rsurface.batchelement3s_indexbuffer = NULL;
9030 rsurface.batchelement3s_bufferoffset = 0;
9031 rsurface.passcolor4f = NULL;
9032 rsurface.passcolor4f_vertexbuffer = NULL;
9033 rsurface.passcolor4f_bufferoffset = 0;
9034 rsurface.forcecurrenttextureupdate = false;
9037 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)
9039 rsurface.entity = r_refdef.scene.worldentity;
9040 rsurface.skeleton = NULL;
9041 rsurface.ent_skinnum = 0;
9042 rsurface.ent_qwskin = -1;
9043 rsurface.ent_flags = entflags;
9044 rsurface.shadertime = r_refdef.scene.time - shadertime;
9045 rsurface.modelnumvertices = numvertices;
9046 rsurface.modelnumtriangles = numtriangles;
9047 rsurface.matrix = *matrix;
9048 rsurface.inversematrix = *inversematrix;
9049 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
9050 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
9051 R_EntityMatrix(&rsurface.matrix);
9052 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
9053 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
9054 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
9055 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
9056 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
9057 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
9058 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
9059 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
9060 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
9061 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
9062 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
9063 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
9064 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
9065 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
9066 rsurface.frameblend[0].lerp = 1;
9067 rsurface.ent_alttextures = false;
9068 rsurface.basepolygonfactor = r_refdef.polygonfactor;
9069 rsurface.basepolygonoffset = r_refdef.polygonoffset;
9070 rsurface.entityskeletaltransform3x4 = NULL;
9071 rsurface.entityskeletaltransform3x4buffer = NULL;
9072 rsurface.entityskeletaltransform3x4offset = 0;
9073 rsurface.entityskeletaltransform3x4size = 0;
9074 rsurface.entityskeletalnumtransforms = 0;
9075 r_refdef.stats[r_stat_batch_entitycustom_count]++;
9076 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
9077 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
9078 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
9081 rsurface.modelvertex3f = (float *)vertex3f;
9082 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9083 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9084 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9086 else if (wantnormals)
9088 rsurface.modelvertex3f = (float *)vertex3f;
9089 rsurface.modelsvector3f = NULL;
9090 rsurface.modeltvector3f = NULL;
9091 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9095 rsurface.modelvertex3f = (float *)vertex3f;
9096 rsurface.modelsvector3f = NULL;
9097 rsurface.modeltvector3f = NULL;
9098 rsurface.modelnormal3f = NULL;
9100 rsurface.modelvertexmesh = NULL;
9101 rsurface.modelvertexmesh_vertexbuffer = NULL;
9102 rsurface.modelvertexmesh_bufferoffset = 0;
9103 rsurface.modelvertex3f_vertexbuffer = 0;
9104 rsurface.modelvertex3f_bufferoffset = 0;
9105 rsurface.modelsvector3f_vertexbuffer = 0;
9106 rsurface.modelsvector3f_bufferoffset = 0;
9107 rsurface.modeltvector3f_vertexbuffer = 0;
9108 rsurface.modeltvector3f_bufferoffset = 0;
9109 rsurface.modelnormal3f_vertexbuffer = 0;
9110 rsurface.modelnormal3f_bufferoffset = 0;
9111 rsurface.modelgeneratedvertex = true;
9112 rsurface.modellightmapcolor4f = (float *)color4f;
9113 rsurface.modellightmapcolor4f_vertexbuffer = 0;
9114 rsurface.modellightmapcolor4f_bufferoffset = 0;
9115 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
9116 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
9117 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
9118 rsurface.modeltexcoordlightmap2f = NULL;
9119 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
9120 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
9121 rsurface.modelskeletalindex4ub = NULL;
9122 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
9123 rsurface.modelskeletalindex4ub_bufferoffset = 0;
9124 rsurface.modelskeletalweight4ub = NULL;
9125 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
9126 rsurface.modelskeletalweight4ub_bufferoffset = 0;
9127 rsurface.modelelement3i = (int *)element3i;
9128 rsurface.modelelement3i_indexbuffer = NULL;
9129 rsurface.modelelement3i_bufferoffset = 0;
9130 rsurface.modelelement3s = (unsigned short *)element3s;
9131 rsurface.modelelement3s_indexbuffer = NULL;
9132 rsurface.modelelement3s_bufferoffset = 0;
9133 rsurface.modellightmapoffsets = NULL;
9134 rsurface.modelsurfaces = NULL;
9135 rsurface.batchgeneratedvertex = false;
9136 rsurface.batchfirstvertex = 0;
9137 rsurface.batchnumvertices = 0;
9138 rsurface.batchfirsttriangle = 0;
9139 rsurface.batchnumtriangles = 0;
9140 rsurface.batchvertex3f = NULL;
9141 rsurface.batchvertex3f_vertexbuffer = NULL;
9142 rsurface.batchvertex3f_bufferoffset = 0;
9143 rsurface.batchsvector3f = NULL;
9144 rsurface.batchsvector3f_vertexbuffer = NULL;
9145 rsurface.batchsvector3f_bufferoffset = 0;
9146 rsurface.batchtvector3f = NULL;
9147 rsurface.batchtvector3f_vertexbuffer = NULL;
9148 rsurface.batchtvector3f_bufferoffset = 0;
9149 rsurface.batchnormal3f = NULL;
9150 rsurface.batchnormal3f_vertexbuffer = NULL;
9151 rsurface.batchnormal3f_bufferoffset = 0;
9152 rsurface.batchlightmapcolor4f = NULL;
9153 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9154 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9155 rsurface.batchtexcoordtexture2f = NULL;
9156 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158 rsurface.batchtexcoordlightmap2f = NULL;
9159 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9160 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9161 rsurface.batchskeletalindex4ub = NULL;
9162 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9163 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9164 rsurface.batchskeletalweight4ub = NULL;
9165 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9166 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9167 rsurface.batchvertexmesh = NULL;
9168 rsurface.batchvertexmesh_vertexbuffer = NULL;
9169 rsurface.batchvertexmesh_bufferoffset = 0;
9170 rsurface.batchelement3i = NULL;
9171 rsurface.batchelement3i_indexbuffer = NULL;
9172 rsurface.batchelement3i_bufferoffset = 0;
9173 rsurface.batchelement3s = NULL;
9174 rsurface.batchelement3s_indexbuffer = NULL;
9175 rsurface.batchelement3s_bufferoffset = 0;
9176 rsurface.passcolor4f = NULL;
9177 rsurface.passcolor4f_vertexbuffer = NULL;
9178 rsurface.passcolor4f_bufferoffset = 0;
9179 rsurface.forcecurrenttextureupdate = true;
9181 if (rsurface.modelnumvertices && rsurface.modelelement3i)
9183 if ((wantnormals || wanttangents) && !normal3f)
9185 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9186 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
9188 if (wanttangents && !svector3f)
9190 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9191 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9192 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9197 float RSurf_FogPoint(const float *v)
9199 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9200 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9201 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9202 float FogHeightFade = r_refdef.fogheightfade;
9204 unsigned int fogmasktableindex;
9205 if (r_refdef.fogplaneviewabove)
9206 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9208 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9209 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9210 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9213 float RSurf_FogVertex(const float *v)
9215 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9216 float FogPlaneViewDist = rsurface.fogplaneviewdist;
9217 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9218 float FogHeightFade = rsurface.fogheightfade;
9220 unsigned int fogmasktableindex;
9221 if (r_refdef.fogplaneviewabove)
9222 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9224 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9225 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9226 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9229 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9232 for (i = 0;i < numelements;i++)
9233 outelement3i[i] = inelement3i[i] + adjust;
9236 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9237 extern cvar_t gl_vbo;
9238 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9246 int surfacefirsttriangle;
9247 int surfacenumtriangles;
9248 int surfacefirstvertex;
9249 int surfaceendvertex;
9250 int surfacenumvertices;
9251 int batchnumsurfaces = texturenumsurfaces;
9252 int batchnumvertices;
9253 int batchnumtriangles;
9257 qboolean dynamicvertex;
9260 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9263 q3shaderinfo_deform_t *deform;
9264 const msurface_t *surface, *firstsurface;
9265 r_vertexmesh_t *vertexmesh;
9266 if (!texturenumsurfaces)
9268 // find vertex range of this surface batch
9270 firstsurface = texturesurfacelist[0];
9271 firsttriangle = firstsurface->num_firsttriangle;
9272 batchnumvertices = 0;
9273 batchnumtriangles = 0;
9274 firstvertex = endvertex = firstsurface->num_firstvertex;
9275 for (i = 0;i < texturenumsurfaces;i++)
9277 surface = texturesurfacelist[i];
9278 if (surface != firstsurface + i)
9280 surfacefirstvertex = surface->num_firstvertex;
9281 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9282 surfacenumvertices = surface->num_vertices;
9283 surfacenumtriangles = surface->num_triangles;
9284 if (firstvertex > surfacefirstvertex)
9285 firstvertex = surfacefirstvertex;
9286 if (endvertex < surfaceendvertex)
9287 endvertex = surfaceendvertex;
9288 batchnumvertices += surfacenumvertices;
9289 batchnumtriangles += surfacenumtriangles;
9292 r_refdef.stats[r_stat_batch_batches]++;
9294 r_refdef.stats[r_stat_batch_withgaps]++;
9295 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9296 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9297 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9299 // we now know the vertex range used, and if there are any gaps in it
9300 rsurface.batchfirstvertex = firstvertex;
9301 rsurface.batchnumvertices = endvertex - firstvertex;
9302 rsurface.batchfirsttriangle = firsttriangle;
9303 rsurface.batchnumtriangles = batchnumtriangles;
9305 // this variable holds flags for which properties have been updated that
9306 // may require regenerating vertexmesh array...
9309 // check if any dynamic vertex processing must occur
9310 dynamicvertex = false;
9312 // a cvar to force the dynamic vertex path to be taken, for debugging
9313 if (r_batch_debugdynamicvertexpath.integer)
9317 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9318 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9319 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9320 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9322 dynamicvertex = true;
9325 // if there is a chance of animated vertex colors, it's a dynamic batch
9326 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9330 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9331 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9332 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9333 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9335 dynamicvertex = true;
9336 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9339 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9341 switch (deform->deform)
9344 case Q3DEFORM_PROJECTIONSHADOW:
9345 case Q3DEFORM_TEXT0:
9346 case Q3DEFORM_TEXT1:
9347 case Q3DEFORM_TEXT2:
9348 case Q3DEFORM_TEXT3:
9349 case Q3DEFORM_TEXT4:
9350 case Q3DEFORM_TEXT5:
9351 case Q3DEFORM_TEXT6:
9352 case Q3DEFORM_TEXT7:
9355 case Q3DEFORM_AUTOSPRITE:
9358 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9359 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9360 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9361 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9363 dynamicvertex = true;
9364 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9365 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9367 case Q3DEFORM_AUTOSPRITE2:
9370 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9371 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9372 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9373 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9375 dynamicvertex = true;
9376 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9377 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9379 case Q3DEFORM_NORMAL:
9382 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9383 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9384 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9385 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9387 dynamicvertex = true;
9388 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9389 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9392 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9393 break; // if wavefunc is a nop, ignore this transform
9396 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9397 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9398 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9399 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9401 dynamicvertex = true;
9402 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9403 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9405 case Q3DEFORM_BULGE:
9408 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9409 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9410 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9411 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9413 dynamicvertex = true;
9414 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9415 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9418 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9419 break; // if wavefunc is a nop, ignore this transform
9422 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9423 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9424 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9425 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9427 dynamicvertex = true;
9428 batchneed |= BATCHNEED_ARRAY_VERTEX;
9429 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9433 if (rsurface.texture->materialshaderpass)
9435 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
9438 case Q3TCGEN_TEXTURE:
9440 case Q3TCGEN_LIGHTMAP:
9443 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9444 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9445 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9446 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9448 dynamicvertex = true;
9449 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9450 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9452 case Q3TCGEN_VECTOR:
9455 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9456 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9457 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9458 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9460 dynamicvertex = true;
9461 batchneed |= BATCHNEED_ARRAY_VERTEX;
9462 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9464 case Q3TCGEN_ENVIRONMENT:
9467 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9468 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9469 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9470 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9472 dynamicvertex = true;
9473 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9474 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9477 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9481 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9482 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9483 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9484 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9486 dynamicvertex = true;
9487 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9488 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9492 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9496 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9497 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9498 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9499 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9501 dynamicvertex = true;
9502 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9505 // when the model data has no vertex buffer (dynamic mesh), we need to
9507 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9508 batchneed |= BATCHNEED_NOGAPS;
9510 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9511 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9512 // we ensure this by treating the vertex batch as dynamic...
9513 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9517 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9518 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9519 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9520 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9522 dynamicvertex = true;
9527 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9528 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9529 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9530 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9531 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9532 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9533 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9534 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9537 // if needsupdate, we have to do a dynamic vertex batch for sure
9538 if (needsupdate & batchneed)
9542 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9543 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9544 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9545 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9547 dynamicvertex = true;
9550 // see if we need to build vertexmesh from arrays
9551 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9555 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9556 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9557 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9558 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9560 dynamicvertex = true;
9563 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9564 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9565 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9567 rsurface.batchvertex3f = rsurface.modelvertex3f;
9568 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9569 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9570 rsurface.batchsvector3f = rsurface.modelsvector3f;
9571 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9572 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9573 rsurface.batchtvector3f = rsurface.modeltvector3f;
9574 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9575 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9576 rsurface.batchnormal3f = rsurface.modelnormal3f;
9577 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9578 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9579 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9580 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9581 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9582 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9583 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9584 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9585 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9586 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9587 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9588 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9589 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9590 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9591 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9592 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9593 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9594 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9595 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9596 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9597 rsurface.batchelement3i = rsurface.modelelement3i;
9598 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9599 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9600 rsurface.batchelement3s = rsurface.modelelement3s;
9601 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9602 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9603 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9604 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9605 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9606 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9607 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9609 // if any dynamic vertex processing has to occur in software, we copy the
9610 // entire surface list together before processing to rebase the vertices
9611 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9613 // if any gaps exist and we do not have a static vertex buffer, we have to
9614 // copy the surface list together to avoid wasting upload bandwidth on the
9615 // vertices in the gaps.
9617 // if gaps exist and we have a static vertex buffer, we can choose whether
9618 // to combine the index buffer ranges into one dynamic index buffer or
9619 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9621 // in many cases the batch is reduced to one draw call.
9623 rsurface.batchmultidraw = false;
9624 rsurface.batchmultidrawnumsurfaces = 0;
9625 rsurface.batchmultidrawsurfacelist = NULL;
9629 // static vertex data, just set pointers...
9630 rsurface.batchgeneratedvertex = false;
9631 // if there are gaps, we want to build a combined index buffer,
9632 // otherwise use the original static buffer with an appropriate offset
9635 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9636 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9637 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9638 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9639 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9641 rsurface.batchmultidraw = true;
9642 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9643 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9646 // build a new triangle elements array for this batch
9647 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9648 rsurface.batchfirsttriangle = 0;
9650 for (i = 0;i < texturenumsurfaces;i++)
9652 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9653 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9654 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9655 numtriangles += surfacenumtriangles;
9657 rsurface.batchelement3i_indexbuffer = NULL;
9658 rsurface.batchelement3i_bufferoffset = 0;
9659 rsurface.batchelement3s = NULL;
9660 rsurface.batchelement3s_indexbuffer = NULL;
9661 rsurface.batchelement3s_bufferoffset = 0;
9662 if (endvertex <= 65536)
9664 // make a 16bit (unsigned short) index array if possible
9665 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9666 for (i = 0;i < numtriangles*3;i++)
9667 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9669 // upload buffer data for the copytriangles batch
9670 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9672 if (rsurface.batchelement3s)
9673 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9674 else if (rsurface.batchelement3i)
9675 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9680 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9681 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9682 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9683 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9688 // something needs software processing, do it for real...
9689 // we only directly handle separate array data in this case and then
9690 // generate interleaved data if needed...
9691 rsurface.batchgeneratedvertex = true;
9692 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9693 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9694 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9695 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9697 // now copy the vertex data into a combined array and make an index array
9698 // (this is what Quake3 does all the time)
9699 // we also apply any skeletal animation here that would have been done in
9700 // the vertex shader, because most of the dynamic vertex animation cases
9701 // need actual vertex positions and normals
9702 //if (dynamicvertex)
9704 rsurface.batchvertexmesh = NULL;
9705 rsurface.batchvertexmesh_vertexbuffer = NULL;
9706 rsurface.batchvertexmesh_bufferoffset = 0;
9707 rsurface.batchvertex3f = NULL;
9708 rsurface.batchvertex3f_vertexbuffer = NULL;
9709 rsurface.batchvertex3f_bufferoffset = 0;
9710 rsurface.batchsvector3f = NULL;
9711 rsurface.batchsvector3f_vertexbuffer = NULL;
9712 rsurface.batchsvector3f_bufferoffset = 0;
9713 rsurface.batchtvector3f = NULL;
9714 rsurface.batchtvector3f_vertexbuffer = NULL;
9715 rsurface.batchtvector3f_bufferoffset = 0;
9716 rsurface.batchnormal3f = NULL;
9717 rsurface.batchnormal3f_vertexbuffer = NULL;
9718 rsurface.batchnormal3f_bufferoffset = 0;
9719 rsurface.batchlightmapcolor4f = NULL;
9720 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9721 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9722 rsurface.batchtexcoordtexture2f = NULL;
9723 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9724 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9725 rsurface.batchtexcoordlightmap2f = NULL;
9726 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9727 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9728 rsurface.batchskeletalindex4ub = NULL;
9729 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9730 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9731 rsurface.batchskeletalweight4ub = NULL;
9732 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9733 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9734 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9735 rsurface.batchelement3i_indexbuffer = NULL;
9736 rsurface.batchelement3i_bufferoffset = 0;
9737 rsurface.batchelement3s = NULL;
9738 rsurface.batchelement3s_indexbuffer = NULL;
9739 rsurface.batchelement3s_bufferoffset = 0;
9740 rsurface.batchskeletaltransform3x4buffer = NULL;
9741 rsurface.batchskeletaltransform3x4offset = 0;
9742 rsurface.batchskeletaltransform3x4size = 0;
9743 // we'll only be setting up certain arrays as needed
9744 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9745 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9746 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9747 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9748 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9749 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9750 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9752 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9753 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9755 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9756 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9757 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9758 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9759 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9760 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9761 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9763 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9764 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9768 for (i = 0;i < texturenumsurfaces;i++)
9770 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9771 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9772 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9773 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9774 // copy only the data requested
9775 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9776 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9777 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9779 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9781 if (rsurface.batchvertex3f)
9782 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9784 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9786 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9788 if (rsurface.modelnormal3f)
9789 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9791 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9793 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9795 if (rsurface.modelsvector3f)
9797 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9798 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9802 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9803 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9806 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9808 if (rsurface.modellightmapcolor4f)
9809 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9811 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9813 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9815 if (rsurface.modeltexcoordtexture2f)
9816 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9818 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9820 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9822 if (rsurface.modeltexcoordlightmap2f)
9823 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9825 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9827 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9829 if (rsurface.modelskeletalindex4ub)
9831 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9832 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9836 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9837 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9838 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9839 for (j = 0;j < surfacenumvertices;j++)
9844 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9845 numvertices += surfacenumvertices;
9846 numtriangles += surfacenumtriangles;
9849 // generate a 16bit index array as well if possible
9850 // (in general, dynamic batches fit)
9851 if (numvertices <= 65536)
9853 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9854 for (i = 0;i < numtriangles*3;i++)
9855 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9858 // since we've copied everything, the batch now starts at 0
9859 rsurface.batchfirstvertex = 0;
9860 rsurface.batchnumvertices = batchnumvertices;
9861 rsurface.batchfirsttriangle = 0;
9862 rsurface.batchnumtriangles = batchnumtriangles;
9865 // apply skeletal animation that would have been done in the vertex shader
9866 if (rsurface.batchskeletaltransform3x4)
9868 const unsigned char *si;
9869 const unsigned char *sw;
9871 const float *b = rsurface.batchskeletaltransform3x4;
9872 float *vp, *vs, *vt, *vn;
9874 float m[3][4], n[3][4];
9875 float tp[3], ts[3], tt[3], tn[3];
9876 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9877 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9878 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9879 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9880 si = rsurface.batchskeletalindex4ub;
9881 sw = rsurface.batchskeletalweight4ub;
9882 vp = rsurface.batchvertex3f;
9883 vs = rsurface.batchsvector3f;
9884 vt = rsurface.batchtvector3f;
9885 vn = rsurface.batchnormal3f;
9886 memset(m[0], 0, sizeof(m));
9887 memset(n[0], 0, sizeof(n));
9888 for (i = 0;i < batchnumvertices;i++)
9890 t[0] = b + si[0]*12;
9893 // common case - only one matrix
9907 else if (sw[2] + sw[3])
9910 t[1] = b + si[1]*12;
9911 t[2] = b + si[2]*12;
9912 t[3] = b + si[3]*12;
9913 w[0] = sw[0] * (1.0f / 255.0f);
9914 w[1] = sw[1] * (1.0f / 255.0f);
9915 w[2] = sw[2] * (1.0f / 255.0f);
9916 w[3] = sw[3] * (1.0f / 255.0f);
9917 // blend the matrices
9918 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9919 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9920 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9921 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9922 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9923 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9924 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9925 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9926 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9927 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9928 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9929 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9934 t[1] = b + si[1]*12;
9935 w[0] = sw[0] * (1.0f / 255.0f);
9936 w[1] = sw[1] * (1.0f / 255.0f);
9937 // blend the matrices
9938 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9939 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9940 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9941 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9942 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9943 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9944 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9945 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9946 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9947 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9948 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9949 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9953 // modify the vertex
9955 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9956 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9957 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9961 // the normal transformation matrix is a set of cross products...
9962 CrossProduct(m[1], m[2], n[0]);
9963 CrossProduct(m[2], m[0], n[1]);
9964 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9966 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9967 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9968 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9969 VectorNormalize(vn);
9974 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9975 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9976 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9977 VectorNormalize(vs);
9980 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9981 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9982 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9983 VectorNormalize(vt);
9988 rsurface.batchskeletaltransform3x4 = NULL;
9989 rsurface.batchskeletalnumtransforms = 0;
9992 // q1bsp surfaces rendered in vertex color mode have to have colors
9993 // calculated based on lightstyles
9994 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9996 // generate color arrays for the surfaces in this list
10000 const int *offsets;
10001 const unsigned char *lm;
10002 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
10003 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10004 rsurface.batchlightmapcolor4f_bufferoffset = 0;
10006 for (i = 0;i < texturenumsurfaces;i++)
10008 surface = texturesurfacelist[i];
10009 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
10010 surfacenumvertices = surface->num_vertices;
10011 if (surface->lightmapinfo->samples)
10013 for (j = 0;j < surfacenumvertices;j++)
10015 lm = surface->lightmapinfo->samples + offsets[j];
10016 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
10017 VectorScale(lm, scale, c);
10018 if (surface->lightmapinfo->styles[1] != 255)
10020 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
10022 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
10023 VectorMA(c, scale, lm, c);
10024 if (surface->lightmapinfo->styles[2] != 255)
10027 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
10028 VectorMA(c, scale, lm, c);
10029 if (surface->lightmapinfo->styles[3] != 255)
10032 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
10033 VectorMA(c, scale, lm, c);
10040 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);
10046 for (j = 0;j < surfacenumvertices;j++)
10048 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
10055 // if vertices are deformed (sprite flares and things in maps, possibly
10056 // water waves, bulges and other deformations), modify the copied vertices
10058 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
10061 switch (deform->deform)
10064 case Q3DEFORM_PROJECTIONSHADOW:
10065 case Q3DEFORM_TEXT0:
10066 case Q3DEFORM_TEXT1:
10067 case Q3DEFORM_TEXT2:
10068 case Q3DEFORM_TEXT3:
10069 case Q3DEFORM_TEXT4:
10070 case Q3DEFORM_TEXT5:
10071 case Q3DEFORM_TEXT6:
10072 case Q3DEFORM_TEXT7:
10073 case Q3DEFORM_NONE:
10075 case Q3DEFORM_AUTOSPRITE:
10076 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10077 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10078 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10079 VectorNormalize(newforward);
10080 VectorNormalize(newright);
10081 VectorNormalize(newup);
10082 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10083 // rsurface.batchvertex3f_vertexbuffer = NULL;
10084 // rsurface.batchvertex3f_bufferoffset = 0;
10085 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
10086 // rsurface.batchsvector3f_vertexbuffer = NULL;
10087 // rsurface.batchsvector3f_bufferoffset = 0;
10088 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
10089 // rsurface.batchtvector3f_vertexbuffer = NULL;
10090 // rsurface.batchtvector3f_bufferoffset = 0;
10091 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10092 // rsurface.batchnormal3f_vertexbuffer = NULL;
10093 // rsurface.batchnormal3f_bufferoffset = 0;
10094 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
10095 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
10096 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10097 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
10098 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);
10099 // a single autosprite surface can contain multiple sprites...
10100 for (j = 0;j < batchnumvertices - 3;j += 4)
10102 VectorClear(center);
10103 for (i = 0;i < 4;i++)
10104 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10105 VectorScale(center, 0.25f, center);
10106 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
10107 VectorCopy(rsurface.batchsvector3f + 3*j, right);
10108 VectorCopy(rsurface.batchtvector3f + 3*j, up);
10109 for (i = 0;i < 4;i++)
10111 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
10112 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
10115 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
10116 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10117 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);
10119 case Q3DEFORM_AUTOSPRITE2:
10120 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
10121 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
10122 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
10123 VectorNormalize(newforward);
10124 VectorNormalize(newright);
10125 VectorNormalize(newup);
10126 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10127 // rsurface.batchvertex3f_vertexbuffer = NULL;
10128 // rsurface.batchvertex3f_bufferoffset = 0;
10130 const float *v1, *v2;
10140 memset(shortest, 0, sizeof(shortest));
10141 // a single autosprite surface can contain multiple sprites...
10142 for (j = 0;j < batchnumvertices - 3;j += 4)
10144 VectorClear(center);
10145 for (i = 0;i < 4;i++)
10146 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
10147 VectorScale(center, 0.25f, center);
10148 // find the two shortest edges, then use them to define the
10149 // axis vectors for rotating around the central axis
10150 for (i = 0;i < 6;i++)
10152 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
10153 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
10154 l = VectorDistance2(v1, v2);
10155 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
10156 if (v1[2] != v2[2])
10157 l += (1.0f / 1024.0f);
10158 if (shortest[0].length2 > l || i == 0)
10160 shortest[1] = shortest[0];
10161 shortest[0].length2 = l;
10162 shortest[0].v1 = v1;
10163 shortest[0].v2 = v2;
10165 else if (shortest[1].length2 > l || i == 1)
10167 shortest[1].length2 = l;
10168 shortest[1].v1 = v1;
10169 shortest[1].v2 = v2;
10172 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
10173 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
10174 // this calculates the right vector from the shortest edge
10175 // and the up vector from the edge midpoints
10176 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
10177 VectorNormalize(right);
10178 VectorSubtract(end, start, up);
10179 VectorNormalize(up);
10180 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
10181 VectorSubtract(rsurface.localvieworigin, center, forward);
10182 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
10183 VectorNegate(forward, forward);
10184 VectorReflect(forward, 0, up, forward);
10185 VectorNormalize(forward);
10186 CrossProduct(up, forward, newright);
10187 VectorNormalize(newright);
10188 // rotate the quad around the up axis vector, this is made
10189 // especially easy by the fact we know the quad is flat,
10190 // so we only have to subtract the center position and
10191 // measure distance along the right vector, and then
10192 // multiply that by the newright vector and add back the
10194 // we also need to subtract the old position to undo the
10195 // displacement from the center, which we do with a
10196 // DotProduct, the subtraction/addition of center is also
10197 // optimized into DotProducts here
10198 l = DotProduct(right, center);
10199 for (i = 0;i < 4;i++)
10201 v1 = rsurface.batchvertex3f + 3*(j+i);
10202 f = DotProduct(right, v1) - l;
10203 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10207 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10209 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10210 // rsurface.batchnormal3f_vertexbuffer = NULL;
10211 // rsurface.batchnormal3f_bufferoffset = 0;
10212 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10214 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10216 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10217 // rsurface.batchsvector3f_vertexbuffer = NULL;
10218 // rsurface.batchsvector3f_bufferoffset = 0;
10219 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10220 // rsurface.batchtvector3f_vertexbuffer = NULL;
10221 // rsurface.batchtvector3f_bufferoffset = 0;
10222 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);
10225 case Q3DEFORM_NORMAL:
10226 // deform the normals to make reflections wavey
10227 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10228 rsurface.batchnormal3f_vertexbuffer = NULL;
10229 rsurface.batchnormal3f_bufferoffset = 0;
10230 for (j = 0;j < batchnumvertices;j++)
10233 float *normal = rsurface.batchnormal3f + 3*j;
10234 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10235 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10236 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10237 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10238 VectorNormalize(normal);
10240 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10242 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10243 // rsurface.batchsvector3f_vertexbuffer = NULL;
10244 // rsurface.batchsvector3f_bufferoffset = 0;
10245 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10246 // rsurface.batchtvector3f_vertexbuffer = NULL;
10247 // rsurface.batchtvector3f_bufferoffset = 0;
10248 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);
10251 case Q3DEFORM_WAVE:
10252 // deform vertex array to make wavey water and flags and such
10253 waveparms[0] = deform->waveparms[0];
10254 waveparms[1] = deform->waveparms[1];
10255 waveparms[2] = deform->waveparms[2];
10256 waveparms[3] = deform->waveparms[3];
10257 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10258 break; // if wavefunc is a nop, don't make a dynamic vertex array
10259 // this is how a divisor of vertex influence on deformation
10260 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10261 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10262 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10263 // rsurface.batchvertex3f_vertexbuffer = NULL;
10264 // rsurface.batchvertex3f_bufferoffset = 0;
10265 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10266 // rsurface.batchnormal3f_vertexbuffer = NULL;
10267 // rsurface.batchnormal3f_bufferoffset = 0;
10268 for (j = 0;j < batchnumvertices;j++)
10270 // if the wavefunc depends on time, evaluate it per-vertex
10273 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10274 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10276 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10278 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10279 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10280 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10282 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10283 // rsurface.batchsvector3f_vertexbuffer = NULL;
10284 // rsurface.batchsvector3f_bufferoffset = 0;
10285 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10286 // rsurface.batchtvector3f_vertexbuffer = NULL;
10287 // rsurface.batchtvector3f_bufferoffset = 0;
10288 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);
10291 case Q3DEFORM_BULGE:
10292 // deform vertex array to make the surface have moving bulges
10293 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10294 // rsurface.batchvertex3f_vertexbuffer = NULL;
10295 // rsurface.batchvertex3f_bufferoffset = 0;
10296 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10297 // rsurface.batchnormal3f_vertexbuffer = NULL;
10298 // rsurface.batchnormal3f_bufferoffset = 0;
10299 for (j = 0;j < batchnumvertices;j++)
10301 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10302 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10304 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10305 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10306 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10308 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10309 // rsurface.batchsvector3f_vertexbuffer = NULL;
10310 // rsurface.batchsvector3f_bufferoffset = 0;
10311 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10312 // rsurface.batchtvector3f_vertexbuffer = NULL;
10313 // rsurface.batchtvector3f_bufferoffset = 0;
10314 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);
10317 case Q3DEFORM_MOVE:
10318 // deform vertex array
10319 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10320 break; // if wavefunc is a nop, don't make a dynamic vertex array
10321 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10322 VectorScale(deform->parms, scale, waveparms);
10323 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10324 // rsurface.batchvertex3f_vertexbuffer = NULL;
10325 // rsurface.batchvertex3f_bufferoffset = 0;
10326 for (j = 0;j < batchnumvertices;j++)
10327 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10332 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
10334 // generate texcoords based on the chosen texcoord source
10335 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
10338 case Q3TCGEN_TEXTURE:
10340 case Q3TCGEN_LIGHTMAP:
10341 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10342 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10343 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10344 if (rsurface.batchtexcoordlightmap2f)
10345 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10347 case Q3TCGEN_VECTOR:
10348 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10349 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10350 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10351 for (j = 0;j < batchnumvertices;j++)
10353 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
10354 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
10357 case Q3TCGEN_ENVIRONMENT:
10358 // make environment reflections using a spheremap
10359 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10360 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10361 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10362 for (j = 0;j < batchnumvertices;j++)
10364 // identical to Q3A's method, but executed in worldspace so
10365 // carried models can be shiny too
10367 float viewer[3], d, reflected[3], worldreflected[3];
10369 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10370 // VectorNormalize(viewer);
10372 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10374 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10375 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10376 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10377 // note: this is proportinal to viewer, so we can normalize later
10379 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10380 VectorNormalize(worldreflected);
10382 // note: this sphere map only uses world x and z!
10383 // so positive and negative y will LOOK THE SAME.
10384 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10385 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10389 // the only tcmod that needs software vertex processing is turbulent, so
10390 // check for it here and apply the changes if needed
10391 // and we only support that as the first one
10392 // (handling a mixture of turbulent and other tcmods would be problematic
10393 // without punting it entirely to a software path)
10394 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10396 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
10397 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
10398 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10399 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10400 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10401 for (j = 0;j < batchnumvertices;j++)
10403 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);
10404 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10409 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10411 // convert the modified arrays to vertex structs
10412 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10413 // rsurface.batchvertexmesh_vertexbuffer = NULL;
10414 // rsurface.batchvertexmesh_bufferoffset = 0;
10415 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10416 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10417 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10418 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10419 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10420 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10421 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10423 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10425 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10426 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10429 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10430 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10431 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10432 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10433 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10434 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10435 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10436 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10437 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10438 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10440 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10442 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10443 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10448 // upload buffer data for the dynamic batch
10449 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10451 if (rsurface.batchvertexmesh)
10452 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10455 if (rsurface.batchvertex3f)
10456 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10457 if (rsurface.batchsvector3f)
10458 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10459 if (rsurface.batchtvector3f)
10460 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10461 if (rsurface.batchnormal3f)
10462 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10463 if (rsurface.batchlightmapcolor4f)
10464 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10465 if (rsurface.batchtexcoordtexture2f)
10466 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10467 if (rsurface.batchtexcoordlightmap2f)
10468 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10469 if (rsurface.batchskeletalindex4ub)
10470 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10471 if (rsurface.batchskeletalweight4ub)
10472 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10474 if (rsurface.batchelement3s)
10475 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10476 else if (rsurface.batchelement3i)
10477 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10481 void RSurf_DrawBatch(void)
10483 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10484 // through the pipeline, killing it earlier in the pipeline would have
10485 // per-surface overhead rather than per-batch overhead, so it's best to
10486 // reject it here, before it hits glDraw.
10487 if (rsurface.batchnumtriangles == 0)
10490 // batch debugging code
10491 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10497 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10498 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10501 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10503 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10505 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10506 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);
10513 if (rsurface.batchmultidraw)
10515 // issue multiple draws rather than copying index data
10516 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10517 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10518 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10519 for (i = 0;i < numsurfaces;)
10521 // combine consecutive surfaces as one draw
10522 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10523 if (surfacelist[j] != surfacelist[k] + 1)
10525 firstvertex = surfacelist[i]->num_firstvertex;
10526 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10527 firsttriangle = surfacelist[i]->num_firsttriangle;
10528 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10529 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);
10535 // there is only one consecutive run of index data (may have been combined)
10536 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);
10540 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10542 // pick the closest matching water plane
10543 int planeindex, vertexindex, bestplaneindex = -1;
10547 r_waterstate_waterplane_t *p;
10548 qboolean prepared = false;
10550 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10552 if(p->camera_entity != rsurface.texture->camera_entity)
10557 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10559 if(rsurface.batchnumvertices == 0)
10562 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10564 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10565 d += fabs(PlaneDiff(vert, &p->plane));
10567 if (bestd > d || bestplaneindex < 0)
10570 bestplaneindex = planeindex;
10573 return bestplaneindex;
10574 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10575 // this situation though, as it might be better to render single larger
10576 // batches with useless stuff (backface culled for example) than to
10577 // render multiple smaller batches
10580 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10583 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10584 rsurface.passcolor4f_vertexbuffer = 0;
10585 rsurface.passcolor4f_bufferoffset = 0;
10586 for (i = 0;i < rsurface.batchnumvertices;i++)
10587 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10590 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10597 if (rsurface.passcolor4f)
10599 // generate color arrays
10600 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10601 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10602 rsurface.passcolor4f_vertexbuffer = 0;
10603 rsurface.passcolor4f_bufferoffset = 0;
10604 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)
10606 f = RSurf_FogVertex(v);
10615 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10616 rsurface.passcolor4f_vertexbuffer = 0;
10617 rsurface.passcolor4f_bufferoffset = 0;
10618 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10620 f = RSurf_FogVertex(v);
10629 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10636 if (!rsurface.passcolor4f)
10638 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10639 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10640 rsurface.passcolor4f_vertexbuffer = 0;
10641 rsurface.passcolor4f_bufferoffset = 0;
10642 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)
10644 f = RSurf_FogVertex(v);
10645 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10646 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10647 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10652 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10657 if (!rsurface.passcolor4f)
10659 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10660 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10661 rsurface.passcolor4f_vertexbuffer = 0;
10662 rsurface.passcolor4f_bufferoffset = 0;
10663 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10672 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10677 if (!rsurface.passcolor4f)
10679 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10680 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10681 rsurface.passcolor4f_vertexbuffer = 0;
10682 rsurface.passcolor4f_bufferoffset = 0;
10683 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10685 c2[0] = c[0] + r_refdef.scene.ambient;
10686 c2[1] = c[1] + r_refdef.scene.ambient;
10687 c2[2] = c[2] + r_refdef.scene.ambient;
10692 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10695 rsurface.passcolor4f = NULL;
10696 rsurface.passcolor4f_vertexbuffer = 0;
10697 rsurface.passcolor4f_bufferoffset = 0;
10698 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10699 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10700 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10701 GL_Color(r, g, b, a);
10702 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10703 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10704 R_Mesh_TexMatrix(0, NULL);
10708 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10710 // TODO: optimize applyfog && applycolor case
10711 // just apply fog if necessary, and tint the fog color array if necessary
10712 rsurface.passcolor4f = NULL;
10713 rsurface.passcolor4f_vertexbuffer = 0;
10714 rsurface.passcolor4f_bufferoffset = 0;
10715 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10716 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10717 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10718 GL_Color(r, g, b, a);
10722 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10725 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10726 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10727 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10728 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10729 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10730 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10731 GL_Color(r, g, b, a);
10735 static void RSurf_DrawBatch_GL11_ClampColor(void)
10740 if (!rsurface.passcolor4f)
10742 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10744 c2[0] = bound(0.0f, c1[0], 1.0f);
10745 c2[1] = bound(0.0f, c1[1], 1.0f);
10746 c2[2] = bound(0.0f, c1[2], 1.0f);
10747 c2[3] = bound(0.0f, c1[3], 1.0f);
10751 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10761 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10762 rsurface.passcolor4f_vertexbuffer = 0;
10763 rsurface.passcolor4f_bufferoffset = 0;
10764 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)
10766 f = -DotProduct(r_refdef.view.forward, n);
10768 f = f * 0.85 + 0.15; // work around so stuff won't get black
10769 f *= r_refdef.lightmapintensity;
10770 Vector4Set(c, f, f, f, 1);
10774 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10776 RSurf_DrawBatch_GL11_ApplyFakeLight();
10777 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10778 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10779 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10780 GL_Color(r, g, b, a);
10784 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10792 vec3_t ambientcolor;
10793 vec3_t diffusecolor;
10797 VectorCopy(rsurface.modellight_lightdir, lightdir);
10798 f = 0.5f * r_refdef.lightmapintensity;
10799 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10800 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10801 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10802 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10803 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10804 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10806 if (VectorLength2(diffusecolor) > 0)
10808 // q3-style directional shading
10809 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10810 rsurface.passcolor4f_vertexbuffer = 0;
10811 rsurface.passcolor4f_bufferoffset = 0;
10812 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)
10814 if ((f = DotProduct(n, lightdir)) > 0)
10815 VectorMA(ambientcolor, f, diffusecolor, c);
10817 VectorCopy(ambientcolor, c);
10824 *applycolor = false;
10828 *r = ambientcolor[0];
10829 *g = ambientcolor[1];
10830 *b = ambientcolor[2];
10831 rsurface.passcolor4f = NULL;
10832 rsurface.passcolor4f_vertexbuffer = 0;
10833 rsurface.passcolor4f_bufferoffset = 0;
10837 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10839 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10840 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10841 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10842 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10843 GL_Color(r, g, b, a);
10847 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10855 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10856 rsurface.passcolor4f_vertexbuffer = 0;
10857 rsurface.passcolor4f_bufferoffset = 0;
10859 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10861 f = 1 - RSurf_FogVertex(v);
10869 void RSurf_SetupDepthAndCulling(void)
10871 // submodels are biased to avoid z-fighting with world surfaces that they
10872 // may be exactly overlapping (avoids z-fighting artifacts on certain
10873 // doors and things in Quake maps)
10874 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10875 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10876 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10877 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10880 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10882 // transparent sky would be ridiculous
10883 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10885 R_SetupShader_Generic_NoTexture(false, false);
10886 skyrenderlater = true;
10887 RSurf_SetupDepthAndCulling();
10888 GL_DepthMask(true);
10889 // LordHavoc: HalfLife maps have freaky skypolys so don't use
10890 // skymasking on them, and Quake3 never did sky masking (unlike
10891 // software Quake and software Quake2), so disable the sky masking
10892 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10893 // and skymasking also looks very bad when noclipping outside the
10894 // level, so don't use it then either.
10895 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10897 R_Mesh_ResetTextureState();
10898 if (skyrendermasked)
10900 R_SetupShader_DepthOrShadow(false, false, false);
10901 // depth-only (masking)
10902 GL_ColorMask(0,0,0,0);
10903 // just to make sure that braindead drivers don't draw
10904 // anything despite that colormask...
10905 GL_BlendFunc(GL_ZERO, GL_ONE);
10906 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10907 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10911 R_SetupShader_Generic_NoTexture(false, false);
10913 GL_BlendFunc(GL_ONE, GL_ZERO);
10914 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10915 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10916 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10919 if (skyrendermasked)
10920 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10922 R_Mesh_ResetTextureState();
10923 GL_Color(1, 1, 1, 1);
10926 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10927 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10928 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10930 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10934 // render screenspace normalmap to texture
10935 GL_DepthMask(true);
10936 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10941 // bind lightmap texture
10943 // water/refraction/reflection/camera surfaces have to be handled specially
10944 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10946 int start, end, startplaneindex;
10947 for (start = 0;start < texturenumsurfaces;start = end)
10949 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10950 if(startplaneindex < 0)
10952 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10953 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10957 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10959 // now that we have a batch using the same planeindex, render it
10960 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10962 // render water or distortion background
10963 GL_DepthMask(true);
10964 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10966 // blend surface on top
10967 GL_DepthMask(false);
10968 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10971 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10973 // render surface with reflection texture as input
10974 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10975 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10982 // render surface batch normally
10983 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10984 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10988 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10990 // OpenGL 1.3 path - anything not completely ancient
10991 qboolean applycolor;
10994 const texturelayer_t *layer;
10995 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10996 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10998 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11001 int layertexrgbscale;
11002 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11004 if (layerindex == 0)
11005 GL_AlphaTest(true);
11008 GL_AlphaTest(false);
11009 GL_DepthFunc(GL_EQUAL);
11012 GL_DepthMask(layer->depthmask && writedepth);
11013 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11014 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
11016 layertexrgbscale = 4;
11017 VectorScale(layer->color, 0.25f, layercolor);
11019 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
11021 layertexrgbscale = 2;
11022 VectorScale(layer->color, 0.5f, layercolor);
11026 layertexrgbscale = 1;
11027 VectorScale(layer->color, 1.0f, layercolor);
11029 layercolor[3] = layer->color[3];
11030 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
11031 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11032 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11033 switch (layer->type)
11035 case TEXTURELAYERTYPE_LITTEXTURE:
11036 // single-pass lightmapped texture with 2x rgbscale
11037 R_Mesh_TexBind(0, r_texture_white);
11038 R_Mesh_TexMatrix(0, NULL);
11039 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11040 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11041 R_Mesh_TexBind(1, layer->texture);
11042 R_Mesh_TexMatrix(1, &layer->texmatrix);
11043 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11044 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11045 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11046 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11047 else if (FAKELIGHT_ENABLED)
11048 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11049 else if (rsurface.uselightmaptexture)
11050 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11052 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11054 case TEXTURELAYERTYPE_TEXTURE:
11055 // singletexture unlit texture with transparency support
11056 R_Mesh_TexBind(0, layer->texture);
11057 R_Mesh_TexMatrix(0, &layer->texmatrix);
11058 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11059 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11060 R_Mesh_TexBind(1, 0);
11061 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11062 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
11064 case TEXTURELAYERTYPE_FOG:
11065 // singletexture fogging
11066 if (layer->texture)
11068 R_Mesh_TexBind(0, layer->texture);
11069 R_Mesh_TexMatrix(0, &layer->texmatrix);
11070 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
11071 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11075 R_Mesh_TexBind(0, 0);
11076 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11078 R_Mesh_TexBind(1, 0);
11079 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11080 // generate a color array for the fog pass
11081 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
11082 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11086 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11089 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11091 GL_DepthFunc(GL_LEQUAL);
11092 GL_AlphaTest(false);
11096 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11098 // OpenGL 1.1 - crusty old voodoo path
11101 const texturelayer_t *layer;
11102 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11103 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11105 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
11107 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11109 if (layerindex == 0)
11110 GL_AlphaTest(true);
11113 GL_AlphaTest(false);
11114 GL_DepthFunc(GL_EQUAL);
11117 GL_DepthMask(layer->depthmask && writedepth);
11118 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
11119 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
11120 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
11121 switch (layer->type)
11123 case TEXTURELAYERTYPE_LITTEXTURE:
11124 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
11126 // two-pass lit texture with 2x rgbscale
11127 // first the lightmap pass
11128 R_Mesh_TexBind(0, r_texture_white);
11129 R_Mesh_TexMatrix(0, NULL);
11130 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11131 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
11132 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11133 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
11134 else if (FAKELIGHT_ENABLED)
11135 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
11136 else if (rsurface.uselightmaptexture)
11137 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
11139 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
11140 // then apply the texture to it
11141 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
11142 R_Mesh_TexBind(0, layer->texture);
11143 R_Mesh_TexMatrix(0, &layer->texmatrix);
11144 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11145 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11146 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);
11150 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
11151 R_Mesh_TexBind(0, layer->texture);
11152 R_Mesh_TexMatrix(0, &layer->texmatrix);
11153 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11154 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11155 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11156 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);
11157 else if (FAKELIGHT_ENABLED)
11158 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);
11160 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);
11163 case TEXTURELAYERTYPE_TEXTURE:
11164 // singletexture unlit texture with transparency support
11165 R_Mesh_TexBind(0, layer->texture);
11166 R_Mesh_TexMatrix(0, &layer->texmatrix);
11167 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11168 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11169 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);
11171 case TEXTURELAYERTYPE_FOG:
11172 // singletexture fogging
11173 if (layer->texture)
11175 R_Mesh_TexBind(0, layer->texture);
11176 R_Mesh_TexMatrix(0, &layer->texmatrix);
11177 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
11178 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
11182 R_Mesh_TexBind(0, 0);
11183 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
11185 // generate a color array for the fog pass
11186 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
11187 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
11191 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
11194 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11196 GL_DepthFunc(GL_LEQUAL);
11197 GL_AlphaTest(false);
11201 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11205 r_vertexgeneric_t *batchvertex;
11208 // R_Mesh_ResetTextureState();
11209 R_SetupShader_Generic_NoTexture(false, false);
11211 if(rsurface.texture && rsurface.texture->currentskinframe)
11213 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11214 c[3] *= rsurface.texture->currentalpha;
11224 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11226 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11227 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11228 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11231 // brighten it up (as texture value 127 means "unlit")
11232 c[0] *= 2 * r_refdef.view.colorscale;
11233 c[1] *= 2 * r_refdef.view.colorscale;
11234 c[2] *= 2 * r_refdef.view.colorscale;
11236 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11237 c[3] *= r_wateralpha.value;
11239 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11241 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11242 GL_DepthMask(false);
11244 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11246 GL_BlendFunc(GL_ONE, GL_ONE);
11247 GL_DepthMask(false);
11249 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11251 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11252 GL_DepthMask(false);
11254 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11256 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11257 GL_DepthMask(false);
11261 GL_BlendFunc(GL_ONE, GL_ZERO);
11262 GL_DepthMask(writedepth);
11265 if (r_showsurfaces.integer == 3)
11267 rsurface.passcolor4f = NULL;
11269 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11271 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11273 rsurface.passcolor4f = NULL;
11274 rsurface.passcolor4f_vertexbuffer = 0;
11275 rsurface.passcolor4f_bufferoffset = 0;
11277 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11279 qboolean applycolor = true;
11282 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11284 r_refdef.lightmapintensity = 1;
11285 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11286 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11288 else if (FAKELIGHT_ENABLED)
11290 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11292 r_refdef.lightmapintensity = r_fakelight_intensity.value;
11293 RSurf_DrawBatch_GL11_ApplyFakeLight();
11294 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11298 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11300 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11301 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11302 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11305 if(!rsurface.passcolor4f)
11306 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11308 RSurf_DrawBatch_GL11_ApplyAmbient();
11309 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11310 if(r_refdef.fogenabled)
11311 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11312 RSurf_DrawBatch_GL11_ClampColor();
11314 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11315 R_SetupShader_Generic_NoTexture(false, false);
11318 else if (!r_refdef.view.showdebug)
11320 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11321 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11322 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11324 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11325 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11327 R_Mesh_PrepareVertices_Generic_Unlock();
11330 else if (r_showsurfaces.integer == 4)
11332 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11333 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11334 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11336 unsigned char d = (vi << 3) * (1.0f / 256.0f);
11337 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11338 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
11340 R_Mesh_PrepareVertices_Generic_Unlock();
11343 else if (r_showsurfaces.integer == 2)
11346 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11347 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11348 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11350 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11351 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11352 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11353 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11354 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
11355 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
11356 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
11358 R_Mesh_PrepareVertices_Generic_Unlock();
11359 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11363 int texturesurfaceindex;
11365 const msurface_t *surface;
11366 float surfacecolor4f[4];
11367 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11368 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11370 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11372 surface = texturesurfacelist[texturesurfaceindex];
11373 k = (int)(((size_t)surface) / sizeof(msurface_t));
11374 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11375 for (j = 0;j < surface->num_vertices;j++)
11377 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11378 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11382 R_Mesh_PrepareVertices_Generic_Unlock();
11387 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11390 RSurf_SetupDepthAndCulling();
11391 if (r_showsurfaces.integer)
11393 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11396 switch (vid.renderpath)
11398 case RENDERPATH_GL20:
11399 case RENDERPATH_D3D9:
11400 case RENDERPATH_D3D10:
11401 case RENDERPATH_D3D11:
11402 case RENDERPATH_SOFT:
11403 case RENDERPATH_GLES2:
11404 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11406 case RENDERPATH_GL13:
11407 case RENDERPATH_GLES1:
11408 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11410 case RENDERPATH_GL11:
11411 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11417 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11420 RSurf_SetupDepthAndCulling();
11421 if (r_showsurfaces.integer)
11423 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11426 switch (vid.renderpath)
11428 case RENDERPATH_GL20:
11429 case RENDERPATH_D3D9:
11430 case RENDERPATH_D3D10:
11431 case RENDERPATH_D3D11:
11432 case RENDERPATH_SOFT:
11433 case RENDERPATH_GLES2:
11434 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11436 case RENDERPATH_GL13:
11437 case RENDERPATH_GLES1:
11438 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11440 case RENDERPATH_GL11:
11441 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11447 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11450 int texturenumsurfaces, endsurface;
11451 texture_t *texture;
11452 const msurface_t *surface;
11453 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11455 // if the model is static it doesn't matter what value we give for
11456 // wantnormals and wanttangents, so this logic uses only rules applicable
11457 // to a model, knowing that they are meaningless otherwise
11458 if (ent == r_refdef.scene.worldentity)
11459 RSurf_ActiveWorldEntity();
11460 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11461 RSurf_ActiveModelEntity(ent, false, false, false);
11464 switch (vid.renderpath)
11466 case RENDERPATH_GL20:
11467 case RENDERPATH_D3D9:
11468 case RENDERPATH_D3D10:
11469 case RENDERPATH_D3D11:
11470 case RENDERPATH_SOFT:
11471 case RENDERPATH_GLES2:
11472 RSurf_ActiveModelEntity(ent, true, true, false);
11474 case RENDERPATH_GL11:
11475 case RENDERPATH_GL13:
11476 case RENDERPATH_GLES1:
11477 RSurf_ActiveModelEntity(ent, true, false, false);
11482 if (r_transparentdepthmasking.integer)
11484 qboolean setup = false;
11485 for (i = 0;i < numsurfaces;i = j)
11488 surface = rsurface.modelsurfaces + surfacelist[i];
11489 texture = surface->texture;
11490 rsurface.texture = R_GetCurrentTexture(texture);
11491 rsurface.lightmaptexture = NULL;
11492 rsurface.deluxemaptexture = NULL;
11493 rsurface.uselightmaptexture = false;
11494 // scan ahead until we find a different texture
11495 endsurface = min(i + 1024, numsurfaces);
11496 texturenumsurfaces = 0;
11497 texturesurfacelist[texturenumsurfaces++] = surface;
11498 for (;j < endsurface;j++)
11500 surface = rsurface.modelsurfaces + surfacelist[j];
11501 if (texture != surface->texture)
11503 texturesurfacelist[texturenumsurfaces++] = surface;
11505 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11507 // render the range of surfaces as depth
11511 GL_ColorMask(0,0,0,0);
11513 GL_DepthTest(true);
11514 GL_BlendFunc(GL_ONE, GL_ZERO);
11515 GL_DepthMask(true);
11516 // R_Mesh_ResetTextureState();
11518 RSurf_SetupDepthAndCulling();
11519 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11520 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11521 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11525 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11528 for (i = 0;i < numsurfaces;i = j)
11531 surface = rsurface.modelsurfaces + surfacelist[i];
11532 texture = surface->texture;
11533 rsurface.texture = R_GetCurrentTexture(texture);
11534 // scan ahead until we find a different texture
11535 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11536 texturenumsurfaces = 0;
11537 texturesurfacelist[texturenumsurfaces++] = surface;
11538 if(FAKELIGHT_ENABLED)
11540 rsurface.lightmaptexture = NULL;
11541 rsurface.deluxemaptexture = NULL;
11542 rsurface.uselightmaptexture = false;
11543 for (;j < endsurface;j++)
11545 surface = rsurface.modelsurfaces + surfacelist[j];
11546 if (texture != surface->texture)
11548 texturesurfacelist[texturenumsurfaces++] = surface;
11553 rsurface.lightmaptexture = surface->lightmaptexture;
11554 rsurface.deluxemaptexture = surface->deluxemaptexture;
11555 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11556 for (;j < endsurface;j++)
11558 surface = rsurface.modelsurfaces + surfacelist[j];
11559 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11561 texturesurfacelist[texturenumsurfaces++] = surface;
11564 // render the range of surfaces
11565 if (ent == r_refdef.scene.worldentity)
11566 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11568 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11570 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11573 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11575 // transparent surfaces get pushed off into the transparent queue
11576 int surfacelistindex;
11577 const msurface_t *surface;
11578 vec3_t tempcenter, center;
11579 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11581 surface = texturesurfacelist[surfacelistindex];
11582 if (r_transparent_sortsurfacesbynearest.integer)
11584 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11585 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11586 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11590 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11591 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11592 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11594 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11595 if (rsurface.entity->transparent_offset) // transparent offset
11597 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11598 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11599 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11601 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);
11605 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11607 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11609 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11611 RSurf_SetupDepthAndCulling();
11612 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11613 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11614 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11618 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11622 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11625 if (!rsurface.texture->currentnumlayers)
11627 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11628 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11630 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11632 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11633 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11634 else if (!rsurface.texture->currentnumlayers)
11636 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11638 // in the deferred case, transparent surfaces were queued during prepass
11639 if (!r_shadow_usingdeferredprepass)
11640 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11644 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11645 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11650 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11653 texture_t *texture;
11654 R_FrameData_SetMark();
11655 // break the surface list down into batches by texture and use of lightmapping
11656 for (i = 0;i < numsurfaces;i = j)
11659 // texture is the base texture pointer, rsurface.texture is the
11660 // current frame/skin the texture is directing us to use (for example
11661 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11662 // use skin 1 instead)
11663 texture = surfacelist[i]->texture;
11664 rsurface.texture = R_GetCurrentTexture(texture);
11665 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11667 // if this texture is not the kind we want, skip ahead to the next one
11668 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11672 if(FAKELIGHT_ENABLED || depthonly || prepass)
11674 rsurface.lightmaptexture = NULL;
11675 rsurface.deluxemaptexture = NULL;
11676 rsurface.uselightmaptexture = false;
11677 // simply scan ahead until we find a different texture or lightmap state
11678 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11683 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11684 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11685 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11686 // simply scan ahead until we find a different texture or lightmap state
11687 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11690 // render the range of surfaces
11691 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11693 R_FrameData_ReturnToMark();
11696 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11700 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11703 if (!rsurface.texture->currentnumlayers)
11705 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11706 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11708 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11710 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11711 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11712 else if (!rsurface.texture->currentnumlayers)
11714 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11716 // in the deferred case, transparent surfaces were queued during prepass
11717 if (!r_shadow_usingdeferredprepass)
11718 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11722 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11723 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11728 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11731 texture_t *texture;
11732 R_FrameData_SetMark();
11733 // break the surface list down into batches by texture and use of lightmapping
11734 for (i = 0;i < numsurfaces;i = j)
11737 // texture is the base texture pointer, rsurface.texture is the
11738 // current frame/skin the texture is directing us to use (for example
11739 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11740 // use skin 1 instead)
11741 texture = surfacelist[i]->texture;
11742 rsurface.texture = R_GetCurrentTexture(texture);
11743 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11745 // if this texture is not the kind we want, skip ahead to the next one
11746 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11750 if(FAKELIGHT_ENABLED || depthonly || prepass)
11752 rsurface.lightmaptexture = NULL;
11753 rsurface.deluxemaptexture = NULL;
11754 rsurface.uselightmaptexture = false;
11755 // simply scan ahead until we find a different texture or lightmap state
11756 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11761 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11762 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11763 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11764 // simply scan ahead until we find a different texture or lightmap state
11765 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11768 // render the range of surfaces
11769 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11771 R_FrameData_ReturnToMark();
11774 float locboxvertex3f[6*4*3] =
11776 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11777 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11778 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11779 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11780 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11781 1,0,0, 0,0,0, 0,1,0, 1,1,0
11784 unsigned short locboxelements[6*2*3] =
11789 12,13,14, 12,14,15,
11790 16,17,18, 16,18,19,
11794 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11797 cl_locnode_t *loc = (cl_locnode_t *)ent;
11799 float vertex3f[6*4*3];
11801 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11802 GL_DepthMask(false);
11803 GL_DepthRange(0, 1);
11804 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11805 GL_DepthTest(true);
11806 GL_CullFace(GL_NONE);
11807 R_EntityMatrix(&identitymatrix);
11809 // R_Mesh_ResetTextureState();
11811 i = surfacelist[0];
11812 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11813 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11814 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11815 surfacelist[0] < 0 ? 0.5f : 0.125f);
11817 if (VectorCompare(loc->mins, loc->maxs))
11819 VectorSet(size, 2, 2, 2);
11820 VectorMA(loc->mins, -0.5f, size, mins);
11824 VectorCopy(loc->mins, mins);
11825 VectorSubtract(loc->maxs, loc->mins, size);
11828 for (i = 0;i < 6*4*3;)
11829 for (j = 0;j < 3;j++, i++)
11830 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11832 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11833 R_SetupShader_Generic_NoTexture(false, false);
11834 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11837 void R_DrawLocs(void)
11840 cl_locnode_t *loc, *nearestloc;
11842 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11843 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11845 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11846 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11850 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11852 if (decalsystem->decals)
11853 Mem_Free(decalsystem->decals);
11854 memset(decalsystem, 0, sizeof(*decalsystem));
11857 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)
11860 tridecal_t *decals;
11863 // expand or initialize the system
11864 if (decalsystem->maxdecals <= decalsystem->numdecals)
11866 decalsystem_t old = *decalsystem;
11867 qboolean useshortelements;
11868 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11869 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11870 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)));
11871 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11872 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11873 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11874 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11875 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11876 if (decalsystem->numdecals)
11877 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11879 Mem_Free(old.decals);
11880 for (i = 0;i < decalsystem->maxdecals*3;i++)
11881 decalsystem->element3i[i] = i;
11882 if (useshortelements)
11883 for (i = 0;i < decalsystem->maxdecals*3;i++)
11884 decalsystem->element3s[i] = i;
11887 // grab a decal and search for another free slot for the next one
11888 decals = decalsystem->decals;
11889 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11890 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11892 decalsystem->freedecal = i;
11893 if (decalsystem->numdecals <= i)
11894 decalsystem->numdecals = i + 1;
11896 // initialize the decal
11898 decal->triangleindex = triangleindex;
11899 decal->surfaceindex = surfaceindex;
11900 decal->decalsequence = decalsequence;
11901 decal->color4f[0][0] = c0[0];
11902 decal->color4f[0][1] = c0[1];
11903 decal->color4f[0][2] = c0[2];
11904 decal->color4f[0][3] = 1;
11905 decal->color4f[1][0] = c1[0];
11906 decal->color4f[1][1] = c1[1];
11907 decal->color4f[1][2] = c1[2];
11908 decal->color4f[1][3] = 1;
11909 decal->color4f[2][0] = c2[0];
11910 decal->color4f[2][1] = c2[1];
11911 decal->color4f[2][2] = c2[2];
11912 decal->color4f[2][3] = 1;
11913 decal->vertex3f[0][0] = v0[0];
11914 decal->vertex3f[0][1] = v0[1];
11915 decal->vertex3f[0][2] = v0[2];
11916 decal->vertex3f[1][0] = v1[0];
11917 decal->vertex3f[1][1] = v1[1];
11918 decal->vertex3f[1][2] = v1[2];
11919 decal->vertex3f[2][0] = v2[0];
11920 decal->vertex3f[2][1] = v2[1];
11921 decal->vertex3f[2][2] = v2[2];
11922 decal->texcoord2f[0][0] = t0[0];
11923 decal->texcoord2f[0][1] = t0[1];
11924 decal->texcoord2f[1][0] = t1[0];
11925 decal->texcoord2f[1][1] = t1[1];
11926 decal->texcoord2f[2][0] = t2[0];
11927 decal->texcoord2f[2][1] = t2[1];
11928 TriangleNormal(v0, v1, v2, decal->plane);
11929 VectorNormalize(decal->plane);
11930 decal->plane[3] = DotProduct(v0, decal->plane);
11933 extern cvar_t cl_decals_bias;
11934 extern cvar_t cl_decals_models;
11935 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11936 // baseparms, parms, temps
11937 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)
11942 const float *vertex3f;
11943 const float *normal3f;
11945 float points[2][9][3];
11952 e = rsurface.modelelement3i + 3*triangleindex;
11954 vertex3f = rsurface.modelvertex3f;
11955 normal3f = rsurface.modelnormal3f;
11959 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11961 index = 3*e[cornerindex];
11962 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11967 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11969 index = 3*e[cornerindex];
11970 VectorCopy(vertex3f + index, v[cornerindex]);
11975 //TriangleNormal(v[0], v[1], v[2], normal);
11976 //if (DotProduct(normal, localnormal) < 0.0f)
11978 // clip by each of the box planes formed from the projection matrix
11979 // if anything survives, we emit the decal
11980 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]);
11983 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]);
11986 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]);
11989 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]);
11992 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]);
11995 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]);
11998 // some part of the triangle survived, so we have to accept it...
12001 // dynamic always uses the original triangle
12003 for (cornerindex = 0;cornerindex < 3;cornerindex++)
12005 index = 3*e[cornerindex];
12006 VectorCopy(vertex3f + index, v[cornerindex]);
12009 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
12011 // convert vertex positions to texcoords
12012 Matrix4x4_Transform(projection, v[cornerindex], temp);
12013 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
12014 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
12015 // calculate distance fade from the projection origin
12016 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
12017 f = bound(0.0f, f, 1.0f);
12018 c[cornerindex][0] = r * f;
12019 c[cornerindex][1] = g * f;
12020 c[cornerindex][2] = b * f;
12021 c[cornerindex][3] = 1.0f;
12022 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
12025 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);
12027 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
12028 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);
12030 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)
12032 matrix4x4_t projection;
12033 decalsystem_t *decalsystem;
12036 const msurface_t *surface;
12037 const msurface_t *surfaces;
12038 const int *surfacelist;
12039 const texture_t *texture;
12041 int numsurfacelist;
12042 int surfacelistindex;
12045 float localorigin[3];
12046 float localnormal[3];
12047 float localmins[3];
12048 float localmaxs[3];
12051 float planes[6][4];
12054 int bih_triangles_count;
12055 int bih_triangles[256];
12056 int bih_surfaces[256];
12058 decalsystem = &ent->decalsystem;
12059 model = ent->model;
12060 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
12062 R_DecalSystem_Reset(&ent->decalsystem);
12066 if (!model->brush.data_leafs && !cl_decals_models.integer)
12068 if (decalsystem->model)
12069 R_DecalSystem_Reset(decalsystem);
12073 if (decalsystem->model != model)
12074 R_DecalSystem_Reset(decalsystem);
12075 decalsystem->model = model;
12077 RSurf_ActiveModelEntity(ent, true, false, false);
12079 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
12080 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
12081 VectorNormalize(localnormal);
12082 localsize = worldsize*rsurface.inversematrixscale;
12083 localmins[0] = localorigin[0] - localsize;
12084 localmins[1] = localorigin[1] - localsize;
12085 localmins[2] = localorigin[2] - localsize;
12086 localmaxs[0] = localorigin[0] + localsize;
12087 localmaxs[1] = localorigin[1] + localsize;
12088 localmaxs[2] = localorigin[2] + localsize;
12090 //VectorCopy(localnormal, planes[4]);
12091 //VectorVectors(planes[4], planes[2], planes[0]);
12092 AnglesFromVectors(angles, localnormal, NULL, false);
12093 AngleVectors(angles, planes[0], planes[2], planes[4]);
12094 VectorNegate(planes[0], planes[1]);
12095 VectorNegate(planes[2], planes[3]);
12096 VectorNegate(planes[4], planes[5]);
12097 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
12098 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
12099 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
12100 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
12101 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
12102 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
12107 matrix4x4_t forwardprojection;
12108 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
12109 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
12114 float projectionvector[4][3];
12115 VectorScale(planes[0], ilocalsize, projectionvector[0]);
12116 VectorScale(planes[2], ilocalsize, projectionvector[1]);
12117 VectorScale(planes[4], ilocalsize, projectionvector[2]);
12118 projectionvector[0][0] = planes[0][0] * ilocalsize;
12119 projectionvector[0][1] = planes[1][0] * ilocalsize;
12120 projectionvector[0][2] = planes[2][0] * ilocalsize;
12121 projectionvector[1][0] = planes[0][1] * ilocalsize;
12122 projectionvector[1][1] = planes[1][1] * ilocalsize;
12123 projectionvector[1][2] = planes[2][1] * ilocalsize;
12124 projectionvector[2][0] = planes[0][2] * ilocalsize;
12125 projectionvector[2][1] = planes[1][2] * ilocalsize;
12126 projectionvector[2][2] = planes[2][2] * ilocalsize;
12127 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
12128 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
12129 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
12130 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
12134 dynamic = model->surfmesh.isanimated;
12135 numsurfacelist = model->nummodelsurfaces;
12136 surfacelist = model->sortedmodelsurfaces;
12137 surfaces = model->data_surfaces;
12140 bih_triangles_count = -1;
12143 if(model->render_bih.numleafs)
12144 bih = &model->render_bih;
12145 else if(model->collision_bih.numleafs)
12146 bih = &model->collision_bih;
12149 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
12150 if(bih_triangles_count == 0)
12152 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
12154 if(bih_triangles_count > 0)
12156 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
12158 surfaceindex = bih_surfaces[triangleindex];
12159 surface = surfaces + surfaceindex;
12160 texture = surface->texture;
12161 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12163 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12165 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
12170 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
12172 surfaceindex = surfacelist[surfacelistindex];
12173 surface = surfaces + surfaceindex;
12174 // check cull box first because it rejects more than any other check
12175 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
12177 // skip transparent surfaces
12178 texture = surface->texture;
12179 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
12181 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
12183 numtriangles = surface->num_triangles;
12184 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
12185 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
12190 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
12191 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)
12193 int renderentityindex;
12194 float worldmins[3];
12195 float worldmaxs[3];
12196 entity_render_t *ent;
12198 if (!cl_decals_newsystem.integer)
12201 worldmins[0] = worldorigin[0] - worldsize;
12202 worldmins[1] = worldorigin[1] - worldsize;
12203 worldmins[2] = worldorigin[2] - worldsize;
12204 worldmaxs[0] = worldorigin[0] + worldsize;
12205 worldmaxs[1] = worldorigin[1] + worldsize;
12206 worldmaxs[2] = worldorigin[2] + worldsize;
12208 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12210 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12212 ent = r_refdef.scene.entities[renderentityindex];
12213 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12216 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12220 typedef struct r_decalsystem_splatqueue_s
12222 vec3_t worldorigin;
12223 vec3_t worldnormal;
12227 unsigned int decalsequence;
12229 r_decalsystem_splatqueue_t;
12231 int r_decalsystem_numqueued = 0;
12232 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12234 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)
12236 r_decalsystem_splatqueue_t *queue;
12238 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12241 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12242 VectorCopy(worldorigin, queue->worldorigin);
12243 VectorCopy(worldnormal, queue->worldnormal);
12244 Vector4Set(queue->color, r, g, b, a);
12245 Vector4Set(queue->tcrange, s1, t1, s2, t2);
12246 queue->worldsize = worldsize;
12247 queue->decalsequence = cl.decalsequence++;
12250 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12253 r_decalsystem_splatqueue_t *queue;
12255 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12256 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);
12257 r_decalsystem_numqueued = 0;
12260 extern cvar_t cl_decals_max;
12261 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12264 decalsystem_t *decalsystem = &ent->decalsystem;
12266 unsigned int killsequence;
12271 if (!decalsystem->numdecals)
12274 if (r_showsurfaces.integer)
12277 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12279 R_DecalSystem_Reset(decalsystem);
12283 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12284 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12286 if (decalsystem->lastupdatetime)
12287 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12290 decalsystem->lastupdatetime = r_refdef.scene.time;
12291 numdecals = decalsystem->numdecals;
12293 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12295 if (decal->color4f[0][3])
12297 decal->lived += frametime;
12298 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12300 memset(decal, 0, sizeof(*decal));
12301 if (decalsystem->freedecal > i)
12302 decalsystem->freedecal = i;
12306 decal = decalsystem->decals;
12307 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12310 // collapse the array by shuffling the tail decals into the gaps
12313 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12314 decalsystem->freedecal++;
12315 if (decalsystem->freedecal == numdecals)
12317 decal[decalsystem->freedecal] = decal[--numdecals];
12320 decalsystem->numdecals = numdecals;
12322 if (numdecals <= 0)
12324 // if there are no decals left, reset decalsystem
12325 R_DecalSystem_Reset(decalsystem);
12329 extern skinframe_t *decalskinframe;
12330 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12333 decalsystem_t *decalsystem = &ent->decalsystem;
12342 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12345 numdecals = decalsystem->numdecals;
12349 if (r_showsurfaces.integer)
12352 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12354 R_DecalSystem_Reset(decalsystem);
12358 // if the model is static it doesn't matter what value we give for
12359 // wantnormals and wanttangents, so this logic uses only rules applicable
12360 // to a model, knowing that they are meaningless otherwise
12361 if (ent == r_refdef.scene.worldentity)
12362 RSurf_ActiveWorldEntity();
12364 RSurf_ActiveModelEntity(ent, false, false, false);
12366 decalsystem->lastupdatetime = r_refdef.scene.time;
12368 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12370 // update vertex positions for animated models
12371 v3f = decalsystem->vertex3f;
12372 c4f = decalsystem->color4f;
12373 t2f = decalsystem->texcoord2f;
12374 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12376 if (!decal->color4f[0][3])
12379 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12383 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12386 // update color values for fading decals
12387 if (decal->lived >= cl_decals_time.value)
12388 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12392 c4f[ 0] = decal->color4f[0][0] * alpha;
12393 c4f[ 1] = decal->color4f[0][1] * alpha;
12394 c4f[ 2] = decal->color4f[0][2] * alpha;
12396 c4f[ 4] = decal->color4f[1][0] * alpha;
12397 c4f[ 5] = decal->color4f[1][1] * alpha;
12398 c4f[ 6] = decal->color4f[1][2] * alpha;
12400 c4f[ 8] = decal->color4f[2][0] * alpha;
12401 c4f[ 9] = decal->color4f[2][1] * alpha;
12402 c4f[10] = decal->color4f[2][2] * alpha;
12405 t2f[0] = decal->texcoord2f[0][0];
12406 t2f[1] = decal->texcoord2f[0][1];
12407 t2f[2] = decal->texcoord2f[1][0];
12408 t2f[3] = decal->texcoord2f[1][1];
12409 t2f[4] = decal->texcoord2f[2][0];
12410 t2f[5] = decal->texcoord2f[2][1];
12412 // update vertex positions for animated models
12413 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12415 e = rsurface.modelelement3i + 3*decal->triangleindex;
12416 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12417 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12418 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12422 VectorCopy(decal->vertex3f[0], v3f);
12423 VectorCopy(decal->vertex3f[1], v3f + 3);
12424 VectorCopy(decal->vertex3f[2], v3f + 6);
12427 if (r_refdef.fogenabled)
12429 alpha = RSurf_FogVertex(v3f);
12430 VectorScale(c4f, alpha, c4f);
12431 alpha = RSurf_FogVertex(v3f + 3);
12432 VectorScale(c4f + 4, alpha, c4f + 4);
12433 alpha = RSurf_FogVertex(v3f + 6);
12434 VectorScale(c4f + 8, alpha, c4f + 8);
12445 r_refdef.stats[r_stat_drawndecals] += numtris;
12447 // now render the decals all at once
12448 // (this assumes they all use one particle font texture!)
12449 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);
12450 // R_Mesh_ResetTextureState();
12451 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12452 GL_DepthMask(false);
12453 GL_DepthRange(0, 1);
12454 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12455 GL_DepthTest(true);
12456 GL_CullFace(GL_NONE);
12457 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12458 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12459 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12463 static void R_DrawModelDecals(void)
12467 // fade faster when there are too many decals
12468 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12469 for (i = 0;i < r_refdef.scene.numentities;i++)
12470 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12472 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12473 for (i = 0;i < r_refdef.scene.numentities;i++)
12474 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12475 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12477 R_DecalSystem_ApplySplatEntitiesQueue();
12479 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12480 for (i = 0;i < r_refdef.scene.numentities;i++)
12481 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12483 r_refdef.stats[r_stat_totaldecals] += numdecals;
12485 if (r_showsurfaces.integer)
12488 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12490 for (i = 0;i < r_refdef.scene.numentities;i++)
12492 if (!r_refdef.viewcache.entityvisible[i])
12494 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12495 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12499 extern cvar_t mod_collision_bih;
12500 static void R_DrawDebugModel(void)
12502 entity_render_t *ent = rsurface.entity;
12503 int i, j, flagsmask;
12504 const msurface_t *surface;
12505 dp_model_t *model = ent->model;
12507 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12510 if (r_showoverdraw.value > 0)
12512 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12513 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12514 R_SetupShader_Generic_NoTexture(false, false);
12515 GL_DepthTest(false);
12516 GL_DepthMask(false);
12517 GL_DepthRange(0, 1);
12518 GL_BlendFunc(GL_ONE, GL_ONE);
12519 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12521 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12523 rsurface.texture = R_GetCurrentTexture(surface->texture);
12524 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12526 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12527 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12528 if (!rsurface.texture->currentlayers->depthmask)
12529 GL_Color(c, 0, 0, 1.0f);
12530 else if (ent == r_refdef.scene.worldentity)
12531 GL_Color(c, c, c, 1.0f);
12533 GL_Color(0, c, 0, 1.0f);
12534 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12538 rsurface.texture = NULL;
12541 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12543 // R_Mesh_ResetTextureState();
12544 R_SetupShader_Generic_NoTexture(false, false);
12545 GL_DepthRange(0, 1);
12546 GL_DepthTest(!r_showdisabledepthtest.integer);
12547 GL_DepthMask(false);
12548 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12550 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12554 qboolean cullbox = false;
12555 const q3mbrush_t *brush;
12556 const bih_t *bih = &model->collision_bih;
12557 const bih_leaf_t *bihleaf;
12558 float vertex3f[3][3];
12559 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12560 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12562 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12564 switch (bihleaf->type)
12567 brush = model->brush.data_brushes + bihleaf->itemindex;
12568 if (brush->colbrushf && brush->colbrushf->numtriangles)
12570 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);
12571 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12572 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12575 case BIH_COLLISIONTRIANGLE:
12576 triangleindex = bihleaf->itemindex;
12577 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12578 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12579 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12580 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);
12581 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12582 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12584 case BIH_RENDERTRIANGLE:
12585 triangleindex = bihleaf->itemindex;
12586 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12587 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12588 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12589 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);
12590 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12591 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12597 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12600 if (r_showtris.integer && qglPolygonMode)
12602 if (r_showdisabledepthtest.integer)
12604 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12605 GL_DepthMask(false);
12609 GL_BlendFunc(GL_ONE, GL_ZERO);
12610 GL_DepthMask(true);
12612 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12613 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12615 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12617 rsurface.texture = R_GetCurrentTexture(surface->texture);
12618 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12620 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12621 if (!rsurface.texture->currentlayers->depthmask)
12622 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12623 else if (ent == r_refdef.scene.worldentity)
12624 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12626 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12627 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12631 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12632 rsurface.texture = NULL;
12635 if (r_shownormals.value != 0 && qglBegin)
12639 if (r_showdisabledepthtest.integer)
12641 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12642 GL_DepthMask(false);
12646 GL_BlendFunc(GL_ONE, GL_ZERO);
12647 GL_DepthMask(true);
12649 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12651 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12653 rsurface.texture = R_GetCurrentTexture(surface->texture);
12654 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12656 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12657 qglBegin(GL_LINES);
12658 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12660 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12662 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12663 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12664 qglVertex3f(v[0], v[1], v[2]);
12665 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12666 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12667 qglVertex3f(v[0], v[1], v[2]);
12670 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12672 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12674 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12675 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12676 qglVertex3f(v[0], v[1], v[2]);
12677 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12678 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12679 qglVertex3f(v[0], v[1], v[2]);
12682 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12684 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12686 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12687 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12688 qglVertex3f(v[0], v[1], v[2]);
12689 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12690 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12691 qglVertex3f(v[0], v[1], v[2]);
12694 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12696 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12698 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12699 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12700 qglVertex3f(v[0], v[1], v[2]);
12701 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12702 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12703 qglVertex3f(v[0], v[1], v[2]);
12710 rsurface.texture = NULL;
12715 int r_maxsurfacelist = 0;
12716 const msurface_t **r_surfacelist = NULL;
12717 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12719 int i, j, endj, flagsmask;
12720 dp_model_t *model = r_refdef.scene.worldmodel;
12721 msurface_t *surfaces;
12722 unsigned char *update;
12723 int numsurfacelist = 0;
12727 if (r_maxsurfacelist < model->num_surfaces)
12729 r_maxsurfacelist = model->num_surfaces;
12731 Mem_Free((msurface_t**)r_surfacelist);
12732 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12735 RSurf_ActiveWorldEntity();
12737 surfaces = model->data_surfaces;
12738 update = model->brushq1.lightmapupdateflags;
12740 // update light styles on this submodel
12741 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12743 model_brush_lightstyleinfo_t *style;
12744 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12746 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12748 int *list = style->surfacelist;
12749 style->value = r_refdef.scene.lightstylevalue[style->style];
12750 for (j = 0;j < style->numsurfaces;j++)
12751 update[list[j]] = true;
12756 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12760 R_DrawDebugModel();
12761 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12765 rsurface.lightmaptexture = NULL;
12766 rsurface.deluxemaptexture = NULL;
12767 rsurface.uselightmaptexture = false;
12768 rsurface.texture = NULL;
12769 rsurface.rtlight = NULL;
12770 numsurfacelist = 0;
12771 // add visible surfaces to draw list
12772 for (i = 0;i < model->nummodelsurfaces;i++)
12774 j = model->sortedmodelsurfaces[i];
12775 if (r_refdef.viewcache.world_surfacevisible[j])
12776 r_surfacelist[numsurfacelist++] = surfaces + j;
12778 // update lightmaps if needed
12779 if (model->brushq1.firstrender)
12781 model->brushq1.firstrender = false;
12782 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12784 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12788 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12789 if (r_refdef.viewcache.world_surfacevisible[j])
12791 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12793 // don't do anything if there were no surfaces
12794 if (!numsurfacelist)
12796 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12799 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12801 // add to stats if desired
12802 if (r_speeds.integer && !skysurfaces && !depthonly)
12804 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12805 for (j = 0;j < numsurfacelist;j++)
12806 r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12809 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12812 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12814 int i, j, endj, flagsmask;
12815 dp_model_t *model = ent->model;
12816 msurface_t *surfaces;
12817 unsigned char *update;
12818 int numsurfacelist = 0;
12822 if (r_maxsurfacelist < model->num_surfaces)
12824 r_maxsurfacelist = model->num_surfaces;
12826 Mem_Free((msurface_t **)r_surfacelist);
12827 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12830 // if the model is static it doesn't matter what value we give for
12831 // wantnormals and wanttangents, so this logic uses only rules applicable
12832 // to a model, knowing that they are meaningless otherwise
12833 if (ent == r_refdef.scene.worldentity)
12834 RSurf_ActiveWorldEntity();
12835 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12836 RSurf_ActiveModelEntity(ent, false, false, false);
12838 RSurf_ActiveModelEntity(ent, true, true, true);
12839 else if (depthonly)
12841 switch (vid.renderpath)
12843 case RENDERPATH_GL20:
12844 case RENDERPATH_D3D9:
12845 case RENDERPATH_D3D10:
12846 case RENDERPATH_D3D11:
12847 case RENDERPATH_SOFT:
12848 case RENDERPATH_GLES2:
12849 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12851 case RENDERPATH_GL11:
12852 case RENDERPATH_GL13:
12853 case RENDERPATH_GLES1:
12854 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12860 switch (vid.renderpath)
12862 case RENDERPATH_GL20:
12863 case RENDERPATH_D3D9:
12864 case RENDERPATH_D3D10:
12865 case RENDERPATH_D3D11:
12866 case RENDERPATH_SOFT:
12867 case RENDERPATH_GLES2:
12868 RSurf_ActiveModelEntity(ent, true, true, false);
12870 case RENDERPATH_GL11:
12871 case RENDERPATH_GL13:
12872 case RENDERPATH_GLES1:
12873 RSurf_ActiveModelEntity(ent, true, false, false);
12878 surfaces = model->data_surfaces;
12879 update = model->brushq1.lightmapupdateflags;
12881 // update light styles
12882 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12884 model_brush_lightstyleinfo_t *style;
12885 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12887 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12889 int *list = style->surfacelist;
12890 style->value = r_refdef.scene.lightstylevalue[style->style];
12891 for (j = 0;j < style->numsurfaces;j++)
12892 update[list[j]] = true;
12897 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12901 R_DrawDebugModel();
12902 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12906 rsurface.lightmaptexture = NULL;
12907 rsurface.deluxemaptexture = NULL;
12908 rsurface.uselightmaptexture = false;
12909 rsurface.texture = NULL;
12910 rsurface.rtlight = NULL;
12911 numsurfacelist = 0;
12912 // add visible surfaces to draw list
12913 for (i = 0;i < model->nummodelsurfaces;i++)
12914 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12915 // don't do anything if there were no surfaces
12916 if (!numsurfacelist)
12918 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12921 // update lightmaps if needed
12925 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12930 R_BuildLightMap(ent, surfaces + j);
12935 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12937 // add to stats if desired
12938 if (r_speeds.integer && !skysurfaces && !depthonly)
12940 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12941 for (j = 0;j < numsurfacelist;j++)
12942 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12945 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12948 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12950 static texture_t texture;
12951 static msurface_t surface;
12952 const msurface_t *surfacelist = &surface;
12954 // fake enough texture and surface state to render this geometry
12956 texture.update_lastrenderframe = -1; // regenerate this texture
12957 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12958 texture.basealpha = 1.0f;
12959 texture.currentskinframe = skinframe;
12960 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12961 texture.offsetmapping = OFFSETMAPPING_OFF;
12962 texture.offsetscale = 1;
12963 texture.specularscalemod = 1;
12964 texture.specularpowermod = 1;
12965 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12966 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12967 // JUST GREP FOR "specularscalemod = 1".
12969 surface.texture = &texture;
12970 surface.num_triangles = numtriangles;
12971 surface.num_firsttriangle = firsttriangle;
12972 surface.num_vertices = numvertices;
12973 surface.num_firstvertex = firstvertex;
12976 rsurface.texture = R_GetCurrentTexture(surface.texture);
12977 rsurface.lightmaptexture = NULL;
12978 rsurface.deluxemaptexture = NULL;
12979 rsurface.uselightmaptexture = false;
12980 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12983 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)
12985 static msurface_t surface;
12986 const msurface_t *surfacelist = &surface;
12988 // fake enough texture and surface state to render this geometry
12989 surface.texture = texture;
12990 surface.num_triangles = numtriangles;
12991 surface.num_firsttriangle = firsttriangle;
12992 surface.num_vertices = numvertices;
12993 surface.num_firstvertex = firstvertex;
12996 rsurface.texture = R_GetCurrentTexture(surface.texture);
12997 rsurface.lightmaptexture = NULL;
12998 rsurface.deluxemaptexture = NULL;
12999 rsurface.uselightmaptexture = false;
13000 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);