2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "dpsoftrast.h"
30 #include "cl_collision.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light (DEPRECATED)"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio (DEPRECATED)"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression) (DEPRECATED)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level (DEPRECATED)"};
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
96 cvar_t r_showbboxes_client = { 0, "r_showbboxes_client", "0", "shows bounding boxes of clientside qc entities, value controls opacity scaling (1 = 10%, 10 = 100%)" };
97 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
98 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
99 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
100 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
101 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
102 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
103 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
104 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
105 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
106 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
107 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
108 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
109 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
110 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
111 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
112 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
113 cvar_t r_cullentities_trace_entityocclusion = { 0, "r_cullentities_trace_entityocclusion", "1", "check for occluding entities such as doors, not just world hull" };
114 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
115 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
116 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
117 cvar_t r_cullentities_trace_expand = {0, "r_cullentities_trace_expand", "0", "box expanded by this many units for entity culling"};
118 cvar_t r_cullentities_trace_pad = {0, "r_cullentities_trace_pad", "8", "accept traces that hit within this many units of the box"};
119 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
120 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"};
121 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
122 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
123 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
125 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps (DEPRECATED)"};
126 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier (DEPRECATED)"};
127 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
129 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"};
130 cvar_t r_fullbright_directed_ambient = {0, "r_fullbright_directed_ambient", "0.5", "ambient light multiplier for directed fullbright"};
131 cvar_t r_fullbright_directed_diffuse = {0, "r_fullbright_directed_diffuse", "0.75", "diffuse light multiplier for directed fullbright"};
132 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"};
133 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"};
135 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
136 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
137 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
138 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."};
139 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
140 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
141 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
142 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."};
143 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
144 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
145 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "0.25", "higher values increase shadowmap quality at a cost of area covered (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
146 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."};
147 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
148 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"};
149 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"};
150 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
151 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
152 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
153 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
154 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
155 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"};
156 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
157 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
158 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
159 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
160 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
162 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
163 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
164 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
165 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
166 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
167 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
168 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
169 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
171 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)"};
172 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"};
174 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
175 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
176 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
178 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"};
179 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"};
180 cvar_t r_rendertarget_debug = {0, "r_rendertarget_debug", "-1", "replaces the view with the contents of the specified render target (by number - note that these can fluctuate depending on scene)"};
181 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"};
182 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
183 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
184 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"};
185 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)"};
186 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)"};
187 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
189 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
190 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)"};
191 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
192 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)"};
193 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
194 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)"};
195 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)"};
196 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
197 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"};
198 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."};
199 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
200 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)"};
201 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)"};
202 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)"};
203 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)"};
204 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)"};
205 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)"};
206 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)"};
207 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)"};
209 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)"};
210 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)"};
211 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
212 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"};
213 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
214 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
215 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
216 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"};
217 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"};
219 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
220 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
221 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
222 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
224 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
225 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
227 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
228 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
229 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
230 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
231 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
232 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
234 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
235 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
236 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
237 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
238 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
239 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
240 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
241 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
242 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
243 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
245 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"};
247 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"};
249 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
251 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
253 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)"};
254 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)"};
255 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
256 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
258 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
259 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"};
261 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."};
263 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)"};
264 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
266 {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
267 {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
268 {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
269 {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
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 const float r_screenvertex3f[12] =
332 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
335 for (i = 0;i < verts;i++)
346 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
349 for (i = 0;i < verts;i++)
359 // FIXME: move this to client?
362 if (gamemode == GAME_NEHAHRA)
364 Cvar_Set("gl_fogenable", "0");
365 Cvar_Set("gl_fogdensity", "0.2");
366 Cvar_Set("gl_fogred", "0.3");
367 Cvar_Set("gl_foggreen", "0.3");
368 Cvar_Set("gl_fogblue", "0.3");
370 r_refdef.fog_density = 0;
371 r_refdef.fog_red = 0;
372 r_refdef.fog_green = 0;
373 r_refdef.fog_blue = 0;
374 r_refdef.fog_alpha = 1;
375 r_refdef.fog_start = 0;
376 r_refdef.fog_end = 16384;
377 r_refdef.fog_height = 1<<30;
378 r_refdef.fog_fadedepth = 128;
379 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
382 static void R_BuildBlankTextures(void)
384 unsigned char data[4];
385 data[2] = 128; // normal X
386 data[1] = 128; // normal Y
387 data[0] = 255; // normal Z
388 data[3] = 255; // height
389 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
399 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
404 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
407 static void R_BuildNoTexture(void)
410 unsigned char pix[16][16][4];
411 // this makes a light grey/dark grey checkerboard texture
412 for (y = 0;y < 16;y++)
414 for (x = 0;x < 16;x++)
416 if ((y < 8) ^ (x < 8))
432 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
435 static void R_BuildWhiteCube(void)
437 unsigned char data[6*1*1*4];
438 memset(data, 255, sizeof(data));
439 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
442 static void R_BuildNormalizationCube(void)
446 vec_t s, t, intensity;
449 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
450 for (side = 0;side < 6;side++)
452 for (y = 0;y < NORMSIZE;y++)
454 for (x = 0;x < NORMSIZE;x++)
456 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
457 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
492 intensity = 127.0f / sqrt(DotProduct(v, v));
493 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
494 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
495 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
496 data[((side*64+y)*64+x)*4+3] = 255;
500 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
504 static void R_BuildFogTexture(void)
508 unsigned char data1[FOGWIDTH][4];
509 //unsigned char data2[FOGWIDTH][4];
512 r_refdef.fogmasktable_start = r_refdef.fog_start;
513 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
514 r_refdef.fogmasktable_range = r_refdef.fogrange;
515 r_refdef.fogmasktable_density = r_refdef.fog_density;
517 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
518 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
520 d = (x * r - r_refdef.fogmasktable_start);
521 if(developer_extra.integer)
522 Con_DPrintf("%f ", d);
524 if (r_fog_exp2.integer)
525 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
527 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
528 if(developer_extra.integer)
529 Con_DPrintf(" : %f ", alpha);
530 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
531 if(developer_extra.integer)
532 Con_DPrintf(" = %f\n", alpha);
533 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
536 for (x = 0;x < FOGWIDTH;x++)
538 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
543 //data2[x][0] = 255 - b;
544 //data2[x][1] = 255 - b;
545 //data2[x][2] = 255 - b;
548 if (r_texture_fogattenuation)
550 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
551 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
555 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
556 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
560 static void R_BuildFogHeightTexture(void)
562 unsigned char *inpixels;
570 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
571 if (r_refdef.fogheighttexturename[0])
572 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
575 r_refdef.fog_height_tablesize = 0;
576 if (r_texture_fogheighttexture)
577 R_FreeTexture(r_texture_fogheighttexture);
578 r_texture_fogheighttexture = NULL;
579 if (r_refdef.fog_height_table2d)
580 Mem_Free(r_refdef.fog_height_table2d);
581 r_refdef.fog_height_table2d = NULL;
582 if (r_refdef.fog_height_table1d)
583 Mem_Free(r_refdef.fog_height_table1d);
584 r_refdef.fog_height_table1d = NULL;
588 r_refdef.fog_height_tablesize = size;
589 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
590 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
591 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
593 // LordHavoc: now the magic - what is that table2d for? it is a cooked
594 // average fog color table accounting for every fog layer between a point
595 // and the camera. (Note: attenuation is handled separately!)
596 for (y = 0;y < size;y++)
598 for (x = 0;x < size;x++)
604 for (j = x;j <= y;j++)
606 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
612 for (j = x;j >= y;j--)
614 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
619 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
620 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
621 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
622 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
625 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
628 //=======================================================================================================================================================
630 static const char *builtinshaderstrings[] =
632 #include "shader_glsl.h"
636 const char *builtinhlslshaderstrings[] =
638 #include "shader_hlsl.h"
642 //=======================================================================================================================================================
644 typedef struct shaderpermutationinfo_s
649 shaderpermutationinfo_t;
651 typedef struct shadermodeinfo_s
653 const char *sourcebasename;
654 const char *extension;
655 const char **builtinshaderstrings;
664 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
665 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
667 {"#define USEDIFFUSE\n", " diffuse"},
668 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
669 {"#define USEVIEWTINT\n", " viewtint"},
670 {"#define USECOLORMAPPING\n", " colormapping"},
671 {"#define USESATURATION\n", " saturation"},
672 {"#define USEFOGINSIDE\n", " foginside"},
673 {"#define USEFOGOUTSIDE\n", " fogoutside"},
674 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
675 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
676 {"#define USEGAMMARAMPS\n", " gammaramps"},
677 {"#define USECUBEFILTER\n", " cubefilter"},
678 {"#define USEGLOW\n", " glow"},
679 {"#define USEBLOOM\n", " bloom"},
680 {"#define USESPECULAR\n", " specular"},
681 {"#define USEPOSTPROCESSING\n", " postprocessing"},
682 {"#define USEREFLECTION\n", " reflection"},
683 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
684 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
685 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
686 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
687 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
688 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
689 {"#define USEALPHAKILL\n", " alphakill"},
690 {"#define USEREFLECTCUBE\n", " reflectcube"},
691 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
692 {"#define USEBOUNCEGRID\n", " bouncegrid"},
693 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
694 {"#define USETRIPPY\n", " trippy"},
695 {"#define USEDEPTHRGB\n", " depthrgb"},
696 {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
697 {"#define USESKELETAL\n", " skeletal"},
698 {"#define USEOCCLUDE\n", " occlude"}
701 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
702 shadermodeinfo_t shadermodeinfo[SHADERLANGUAGE_COUNT][SHADERMODE_COUNT] =
704 // SHADERLANGUAGE_GLSL
706 {"combined", "glsl", builtinshaderstrings, "#define MODE_GENERIC\n", " generic"},
707 {"combined", "glsl", builtinshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
708 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
709 {"combined", "glsl", builtinshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
710 {"combined", "glsl", builtinshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
711 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
712 {"combined", "glsl", builtinshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
713 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
714 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
715 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
716 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
717 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
718 {"combined", "glsl", builtinshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
719 {"combined", "glsl", builtinshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
720 {"combined", "glsl", builtinshaderstrings, "#define MODE_WATER\n", " water"},
721 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
722 {"combined", "glsl", builtinshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
724 // SHADERLANGUAGE_HLSL
726 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_GENERIC\n", " generic"},
727 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_POSTPROCESS\n", " postprocess"},
728 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
729 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FLATCOLOR\n", " flatcolor"},
730 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
731 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTMAP\n", " lightmap"},
732 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_FAKELIGHT\n", " fakelight"},
733 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
734 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
735 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
736 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
737 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
738 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_LIGHTSOURCE\n", " lightsource"},
739 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_REFRACTION\n", " refraction"},
740 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_WATER\n", " water"},
741 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
742 {"combined", "hlsl", builtinhlslshaderstrings, "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
746 struct r_glsl_permutation_s;
747 typedef struct r_glsl_permutation_s
750 struct r_glsl_permutation_s *hashnext;
752 dpuint64 permutation;
754 /// indicates if we have tried compiling this permutation already
756 /// 0 if compilation failed
758 // texture units assigned to each detected uniform
759 int tex_Texture_First;
760 int tex_Texture_Second;
761 int tex_Texture_GammaRamps;
762 int tex_Texture_Normal;
763 int tex_Texture_Color;
764 int tex_Texture_Gloss;
765 int tex_Texture_Glow;
766 int tex_Texture_SecondaryNormal;
767 int tex_Texture_SecondaryColor;
768 int tex_Texture_SecondaryGloss;
769 int tex_Texture_SecondaryGlow;
770 int tex_Texture_Pants;
771 int tex_Texture_Shirt;
772 int tex_Texture_FogHeightTexture;
773 int tex_Texture_FogMask;
774 int tex_Texture_Lightmap;
775 int tex_Texture_Deluxemap;
776 int tex_Texture_Attenuation;
777 int tex_Texture_Cube;
778 int tex_Texture_Refraction;
779 int tex_Texture_Reflection;
780 int tex_Texture_ShadowMap2D;
781 int tex_Texture_CubeProjection;
782 int tex_Texture_ScreenNormalMap;
783 int tex_Texture_ScreenDiffuse;
784 int tex_Texture_ScreenSpecular;
785 int tex_Texture_ReflectMask;
786 int tex_Texture_ReflectCube;
787 int tex_Texture_BounceGrid;
788 /// locations of detected uniforms in program object, or -1 if not found
789 int loc_Texture_First;
790 int loc_Texture_Second;
791 int loc_Texture_GammaRamps;
792 int loc_Texture_Normal;
793 int loc_Texture_Color;
794 int loc_Texture_Gloss;
795 int loc_Texture_Glow;
796 int loc_Texture_SecondaryNormal;
797 int loc_Texture_SecondaryColor;
798 int loc_Texture_SecondaryGloss;
799 int loc_Texture_SecondaryGlow;
800 int loc_Texture_Pants;
801 int loc_Texture_Shirt;
802 int loc_Texture_FogHeightTexture;
803 int loc_Texture_FogMask;
804 int loc_Texture_Lightmap;
805 int loc_Texture_Deluxemap;
806 int loc_Texture_Attenuation;
807 int loc_Texture_Cube;
808 int loc_Texture_Refraction;
809 int loc_Texture_Reflection;
810 int loc_Texture_ShadowMap2D;
811 int loc_Texture_CubeProjection;
812 int loc_Texture_ScreenNormalMap;
813 int loc_Texture_ScreenDiffuse;
814 int loc_Texture_ScreenSpecular;
815 int loc_Texture_ReflectMask;
816 int loc_Texture_ReflectCube;
817 int loc_Texture_BounceGrid;
819 int loc_BloomBlur_Parameters;
821 int loc_Color_Ambient;
822 int loc_Color_Diffuse;
823 int loc_Color_Specular;
827 int loc_DeferredColor_Ambient;
828 int loc_DeferredColor_Diffuse;
829 int loc_DeferredColor_Specular;
830 int loc_DeferredMod_Diffuse;
831 int loc_DeferredMod_Specular;
832 int loc_DistortScaleRefractReflect;
835 int loc_FogHeightFade;
837 int loc_FogPlaneViewDist;
838 int loc_FogRangeRecip;
841 int loc_LightPosition;
842 int loc_OffsetMapping_ScaleSteps;
843 int loc_OffsetMapping_LodDistance;
844 int loc_OffsetMapping_Bias;
846 int loc_ReflectColor;
847 int loc_ReflectFactor;
848 int loc_ReflectOffset;
849 int loc_RefractColor;
851 int loc_ScreenCenterRefractReflect;
852 int loc_ScreenScaleRefractReflect;
853 int loc_ScreenToDepth;
854 int loc_ShadowMap_Parameters;
855 int loc_ShadowMap_TextureScale;
856 int loc_SpecularPower;
857 int loc_Skeletal_Transform12;
862 int loc_ViewTintColor;
864 int loc_ModelToLight;
866 int loc_BackgroundTexMatrix;
867 int loc_ModelViewProjectionMatrix;
868 int loc_ModelViewMatrix;
869 int loc_PixelToScreenTexCoord;
870 int loc_ModelToReflectCube;
871 int loc_ShadowMapMatrix;
872 int loc_BloomColorSubtract;
873 int loc_NormalmapScrollBlend;
874 int loc_BounceGridMatrix;
875 int loc_BounceGridIntensity;
876 /// uniform block bindings
877 int ubibind_Skeletal_Transform12_UniformBlock;
878 /// uniform block indices
879 int ubiloc_Skeletal_Transform12_UniformBlock;
881 r_glsl_permutation_t;
883 #define SHADERPERMUTATION_HASHSIZE 256
886 // non-degradable "lightweight" shader parameters to keep the permutations simpler
887 // these can NOT degrade! only use for simple stuff
890 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
891 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
892 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
893 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
894 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
895 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
896 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
897 SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7, ///< LOD for offsetmapping
898 SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
899 SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
900 SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
901 SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
902 SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
903 SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
905 #define SHADERSTATICPARMS_COUNT 14
907 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
908 static int shaderstaticparms_count = 0;
910 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
911 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
913 extern qboolean r_shadow_shadowmapsampler;
914 extern int r_shadow_shadowmappcf;
915 qboolean R_CompileShader_CheckStaticParms(void)
917 static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
918 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
919 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
922 if (r_glsl_saturation_redcompensate.integer)
923 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
924 if (r_glsl_vertextextureblend_usebothalphas.integer)
925 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
926 if (r_shadow_glossexact.integer)
927 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
928 if (r_glsl_postprocess.integer)
930 if (r_glsl_postprocess_uservec1_enable.integer)
931 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
932 if (r_glsl_postprocess_uservec2_enable.integer)
933 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
934 if (r_glsl_postprocess_uservec3_enable.integer)
935 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
936 if (r_glsl_postprocess_uservec4_enable.integer)
937 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
940 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
941 if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
942 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
944 if (r_shadow_shadowmapsampler)
945 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
946 if (r_shadow_shadowmappcf > 1)
947 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
948 else if (r_shadow_shadowmappcf)
949 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
950 if (r_celshading.integer)
951 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
952 if (r_celoutlines.integer)
953 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
955 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
958 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
959 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
960 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
962 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
963 static void R_CompileShader_AddStaticParms(unsigned int mode, dpuint64 permutation)
965 shaderstaticparms_count = 0;
968 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
969 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
970 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
971 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
972 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
973 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
974 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
975 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
976 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
977 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
978 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
979 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
980 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
981 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
984 /// information about each possible shader permutation
985 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
986 /// currently selected permutation
987 r_glsl_permutation_t *r_glsl_permutation;
988 /// storage for permutations linked in the hash table
989 memexpandablearray_t r_glsl_permutationarray;
991 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
993 //unsigned int hashdepth = 0;
994 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
995 r_glsl_permutation_t *p;
996 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
998 if (p->mode == mode && p->permutation == permutation)
1000 //if (hashdepth > 10)
1001 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1006 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1008 p->permutation = permutation;
1009 p->hashnext = r_glsl_permutationhash[mode][hashindex];
1010 r_glsl_permutationhash[mode][hashindex] = p;
1011 //if (hashdepth > 10)
1012 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1016 static char *R_ShaderStrCat(const char **strings)
1019 const char **p = strings;
1022 for (p = strings;(t = *p);p++)
1025 s = string = (char *)Mem_Alloc(r_main_mempool, len);
1027 for (p = strings;(t = *p);p++)
1037 static char *R_ShaderStrCat(const char **strings);
1038 static void R_InitShaderModeInfo(void)
1041 shadermodeinfo_t *modeinfo;
1042 // 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)
1043 for (language = 0; language < SHADERLANGUAGE_COUNT; language++)
1045 for (i = 0; i < SHADERMODE_COUNT; i++)
1047 char filename[MAX_QPATH];
1048 modeinfo = &shadermodeinfo[language][i];
1049 modeinfo->builtinstring = R_ShaderStrCat(modeinfo->builtinshaderstrings);
1050 modeinfo->builtincrc = CRC_Block((const unsigned char *)modeinfo->builtinstring, strlen(modeinfo->builtinstring));
1051 dpsnprintf(filename, sizeof(filename), "%s/%s_crc%i.%s", modeinfo->extension, modeinfo->sourcebasename, modeinfo->builtincrc, modeinfo->extension);
1052 modeinfo->filename = Mem_strdup(r_main_mempool, filename);
1057 static char *ShaderModeInfo_GetShaderText(shadermodeinfo_t *modeinfo, qboolean printfromdisknotice, qboolean builtinonly)
1060 // if the mode has no filename we have to return the builtin string
1061 if (builtinonly || !modeinfo->filename)
1062 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1063 // note that FS_LoadFile appends a 0 byte to make it a valid string
1064 shaderstring = (char *)FS_LoadFile(modeinfo->filename, r_main_mempool, false, NULL);
1067 if (printfromdisknotice)
1068 Con_DPrintf("Loading shaders from file %s...\n", modeinfo->filename);
1069 return shaderstring;
1071 // fall back to builtinstring
1072 return Mem_strdup(r_main_mempool, modeinfo->builtinstring);
1075 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1080 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_GLSL][mode];
1082 char permutationname[256];
1083 int vertstrings_count = 0;
1084 int geomstrings_count = 0;
1085 int fragstrings_count = 0;
1086 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1087 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1088 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095 permutationname[0] = 0;
1096 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1098 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1100 // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1101 if(vid.support.glshaderversion >= 140)
1103 vertstrings_list[vertstrings_count++] = "#version 140\n";
1104 geomstrings_list[geomstrings_count++] = "#version 140\n";
1105 fragstrings_list[fragstrings_count++] = "#version 140\n";
1106 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1107 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1108 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1110 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1111 else if(vid.support.glshaderversion >= 130)
1113 vertstrings_list[vertstrings_count++] = "#version 130\n";
1114 geomstrings_list[geomstrings_count++] = "#version 130\n";
1115 fragstrings_list[fragstrings_count++] = "#version 130\n";
1116 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1117 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1118 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1120 // if we can do #version 120, we should (this adds the invariant keyword)
1121 else if(vid.support.glshaderversion >= 120)
1123 vertstrings_list[vertstrings_count++] = "#version 120\n";
1124 geomstrings_list[geomstrings_count++] = "#version 120\n";
1125 fragstrings_list[fragstrings_count++] = "#version 120\n";
1126 vertstrings_list[vertstrings_count++] = "#define GLSL120\n";
1127 geomstrings_list[geomstrings_count++] = "#define GLSL120\n";
1128 fragstrings_list[fragstrings_count++] = "#define GLSL120\n";
1130 // GLES also adds several things from GLSL120
1131 switch(vid.renderpath)
1133 case RENDERPATH_GLES2:
1134 vertstrings_list[vertstrings_count++] = "#define GLES\n";
1135 geomstrings_list[geomstrings_count++] = "#define GLES\n";
1136 fragstrings_list[fragstrings_count++] = "#define GLES\n";
1142 // the first pretext is which type of shader to compile as
1143 // (later these will all be bound together as a program object)
1144 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1145 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1146 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1148 // the second pretext is the mode (for example a light source)
1149 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1150 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1151 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1152 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1154 // now add all the permutation pretexts
1155 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1157 if (permutation & (1ll<<i))
1159 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1160 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1161 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1162 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1166 // keep line numbers correct
1167 vertstrings_list[vertstrings_count++] = "\n";
1168 geomstrings_list[geomstrings_count++] = "\n";
1169 fragstrings_list[fragstrings_count++] = "\n";
1174 R_CompileShader_AddStaticParms(mode, permutation);
1175 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1176 vertstrings_count += shaderstaticparms_count;
1177 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1178 geomstrings_count += shaderstaticparms_count;
1179 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1180 fragstrings_count += shaderstaticparms_count;
1182 // now append the shader text itself
1183 vertstrings_list[vertstrings_count++] = sourcestring;
1184 geomstrings_list[geomstrings_count++] = sourcestring;
1185 fragstrings_list[fragstrings_count++] = sourcestring;
1187 // compile the shader program
1188 if (vertstrings_count + geomstrings_count + fragstrings_count)
1189 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1193 qglUseProgram(p->program);CHECKGLERROR
1194 // look up all the uniform variable names we care about, so we don't
1195 // have to look them up every time we set them
1200 GLint activeuniformindex = 0;
1201 GLint numactiveuniforms = 0;
1202 char uniformname[128];
1203 GLsizei uniformnamelength = 0;
1204 GLint uniformsize = 0;
1205 GLenum uniformtype = 0;
1206 memset(uniformname, 0, sizeof(uniformname));
1207 qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1208 Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1209 for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1211 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1212 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1217 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1218 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1219 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1220 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1221 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1222 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1223 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1224 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1225 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1226 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1227 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1228 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1229 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1230 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1231 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1232 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1233 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1234 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1235 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1236 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1237 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1238 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1239 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1240 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1241 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1242 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1243 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1244 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1245 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1246 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1247 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1248 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1249 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1250 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1251 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1252 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1253 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1254 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1255 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1256 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1257 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1258 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1259 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1260 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1261 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1262 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1263 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1264 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1265 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1266 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1267 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1268 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1269 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1270 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1271 p->loc_OffsetMapping_LodDistance = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1272 p->loc_OffsetMapping_Bias = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1273 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1274 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1275 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1276 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1277 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1278 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1279 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1280 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1281 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1282 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1283 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1284 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1285 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1286 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1287 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1288 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1289 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1290 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1291 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1292 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1293 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1294 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1295 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1296 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1297 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1298 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1299 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1300 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1301 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1302 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1303 // initialize the samplers to refer to the texture units we use
1304 p->tex_Texture_First = -1;
1305 p->tex_Texture_Second = -1;
1306 p->tex_Texture_GammaRamps = -1;
1307 p->tex_Texture_Normal = -1;
1308 p->tex_Texture_Color = -1;
1309 p->tex_Texture_Gloss = -1;
1310 p->tex_Texture_Glow = -1;
1311 p->tex_Texture_SecondaryNormal = -1;
1312 p->tex_Texture_SecondaryColor = -1;
1313 p->tex_Texture_SecondaryGloss = -1;
1314 p->tex_Texture_SecondaryGlow = -1;
1315 p->tex_Texture_Pants = -1;
1316 p->tex_Texture_Shirt = -1;
1317 p->tex_Texture_FogHeightTexture = -1;
1318 p->tex_Texture_FogMask = -1;
1319 p->tex_Texture_Lightmap = -1;
1320 p->tex_Texture_Deluxemap = -1;
1321 p->tex_Texture_Attenuation = -1;
1322 p->tex_Texture_Cube = -1;
1323 p->tex_Texture_Refraction = -1;
1324 p->tex_Texture_Reflection = -1;
1325 p->tex_Texture_ShadowMap2D = -1;
1326 p->tex_Texture_CubeProjection = -1;
1327 p->tex_Texture_ScreenNormalMap = -1;
1328 p->tex_Texture_ScreenDiffuse = -1;
1329 p->tex_Texture_ScreenSpecular = -1;
1330 p->tex_Texture_ReflectMask = -1;
1331 p->tex_Texture_ReflectCube = -1;
1332 p->tex_Texture_BounceGrid = -1;
1333 // bind the texture samplers in use
1335 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1336 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1337 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1338 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1339 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1340 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1341 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1342 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1343 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1344 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1345 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1346 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1347 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1348 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1349 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1350 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1351 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1352 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1353 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1354 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1355 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1356 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1357 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1358 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1359 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1360 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1361 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1362 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1363 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1364 // get the uniform block indices so we can bind them
1365 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1366 if (vid.support.arb_uniform_buffer_object)
1367 p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1370 p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1371 // clear the uniform block bindings
1372 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1373 // bind the uniform blocks in use
1375 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1376 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1378 // we're done compiling and setting up the shader, at least until it is used
1380 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1383 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1387 Mem_Free(sourcestring);
1390 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, dpuint64 permutation)
1392 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1393 if (r_glsl_permutation != perm)
1395 r_glsl_permutation = perm;
1396 if (!r_glsl_permutation->program)
1398 if (!r_glsl_permutation->compiled)
1400 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1401 R_GLSL_CompilePermutation(perm, mode, permutation);
1403 if (!r_glsl_permutation->program)
1405 // remove features until we find a valid permutation
1407 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1409 // reduce i more quickly whenever it would not remove any bits
1410 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1411 if (!(permutation & j))
1414 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1415 if (!r_glsl_permutation->compiled)
1416 R_GLSL_CompilePermutation(perm, mode, permutation);
1417 if (r_glsl_permutation->program)
1420 if (i >= SHADERPERMUTATION_COUNT)
1422 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1423 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1424 qglUseProgram(0);CHECKGLERROR
1425 return; // no bit left to clear, entire mode is broken
1430 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1432 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1433 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1434 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1442 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1443 extern D3DCAPS9 vid_d3d9caps;
1446 struct r_hlsl_permutation_s;
1447 typedef struct r_hlsl_permutation_s
1449 /// hash lookup data
1450 struct r_hlsl_permutation_s *hashnext;
1452 dpuint64 permutation;
1454 /// indicates if we have tried compiling this permutation already
1456 /// NULL if compilation failed
1457 IDirect3DVertexShader9 *vertexshader;
1458 IDirect3DPixelShader9 *pixelshader;
1460 r_hlsl_permutation_t;
1462 typedef enum D3DVSREGISTER_e
1464 D3DVSREGISTER_TexMatrix = 0, // float4x4
1465 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1466 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1467 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1468 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1469 D3DVSREGISTER_ModelToLight = 20, // float4x4
1470 D3DVSREGISTER_EyePosition = 24,
1471 D3DVSREGISTER_FogPlane = 25,
1472 D3DVSREGISTER_LightDir = 26,
1473 D3DVSREGISTER_LightPosition = 27,
1477 typedef enum D3DPSREGISTER_e
1479 D3DPSREGISTER_Alpha = 0,
1480 D3DPSREGISTER_BloomBlur_Parameters = 1,
1481 D3DPSREGISTER_ClientTime = 2,
1482 D3DPSREGISTER_Color_Ambient = 3,
1483 D3DPSREGISTER_Color_Diffuse = 4,
1484 D3DPSREGISTER_Color_Specular = 5,
1485 D3DPSREGISTER_Color_Glow = 6,
1486 D3DPSREGISTER_Color_Pants = 7,
1487 D3DPSREGISTER_Color_Shirt = 8,
1488 D3DPSREGISTER_DeferredColor_Ambient = 9,
1489 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1490 D3DPSREGISTER_DeferredColor_Specular = 11,
1491 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1492 D3DPSREGISTER_DeferredMod_Specular = 13,
1493 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1494 D3DPSREGISTER_EyePosition = 15, // unused
1495 D3DPSREGISTER_FogColor = 16,
1496 D3DPSREGISTER_FogHeightFade = 17,
1497 D3DPSREGISTER_FogPlane = 18,
1498 D3DPSREGISTER_FogPlaneViewDist = 19,
1499 D3DPSREGISTER_FogRangeRecip = 20,
1500 D3DPSREGISTER_LightColor = 21,
1501 D3DPSREGISTER_LightDir = 22, // unused
1502 D3DPSREGISTER_LightPosition = 23,
1503 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1504 D3DPSREGISTER_PixelSize = 25,
1505 D3DPSREGISTER_ReflectColor = 26,
1506 D3DPSREGISTER_ReflectFactor = 27,
1507 D3DPSREGISTER_ReflectOffset = 28,
1508 D3DPSREGISTER_RefractColor = 29,
1509 D3DPSREGISTER_Saturation = 30,
1510 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1511 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1512 D3DPSREGISTER_ScreenToDepth = 33,
1513 D3DPSREGISTER_ShadowMap_Parameters = 34,
1514 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1515 D3DPSREGISTER_SpecularPower = 36,
1516 D3DPSREGISTER_UserVec1 = 37,
1517 D3DPSREGISTER_UserVec2 = 38,
1518 D3DPSREGISTER_UserVec3 = 39,
1519 D3DPSREGISTER_UserVec4 = 40,
1520 D3DPSREGISTER_ViewTintColor = 41,
1521 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1522 D3DPSREGISTER_BloomColorSubtract = 43,
1523 D3DPSREGISTER_ViewToLight = 44, // float4x4
1524 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1525 D3DPSREGISTER_NormalmapScrollBlend = 52,
1526 D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1527 D3DPSREGISTER_OffsetMapping_Bias = 54,
1532 /// information about each possible shader permutation
1533 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1534 /// currently selected permutation
1535 r_hlsl_permutation_t *r_hlsl_permutation;
1536 /// storage for permutations linked in the hash table
1537 memexpandablearray_t r_hlsl_permutationarray;
1539 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, dpuint64 permutation)
1541 //unsigned int hashdepth = 0;
1542 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1543 r_hlsl_permutation_t *p;
1544 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1546 if (p->mode == mode && p->permutation == permutation)
1548 //if (hashdepth > 10)
1549 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1554 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1556 p->permutation = permutation;
1557 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1558 r_hlsl_permutationhash[mode][hashindex] = p;
1559 //if (hashdepth > 10)
1560 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1565 //#include <d3dx9shader.h>
1566 //#include <d3dx9mesh.h>
1568 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1570 DWORD *vsbin = NULL;
1571 DWORD *psbin = NULL;
1572 fs_offset_t vsbinsize;
1573 fs_offset_t psbinsize;
1574 // IDirect3DVertexShader9 *vs = NULL;
1575 // IDirect3DPixelShader9 *ps = NULL;
1576 ID3DXBuffer *vslog = NULL;
1577 ID3DXBuffer *vsbuffer = NULL;
1578 ID3DXConstantTable *vsconstanttable = NULL;
1579 ID3DXBuffer *pslog = NULL;
1580 ID3DXBuffer *psbuffer = NULL;
1581 ID3DXConstantTable *psconstanttable = NULL;
1584 char temp[MAX_INPUTLINE];
1585 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1587 qboolean debugshader = gl_paranoid.integer != 0;
1588 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1589 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1592 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1593 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1595 if ((!vsbin && vertstring) || (!psbin && fragstring))
1597 const char* dllnames_d3dx9 [] =
1621 dllhandle_t d3dx9_dll = NULL;
1622 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1623 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1624 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1625 dllfunction_t d3dx9_dllfuncs[] =
1627 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1628 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1629 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1632 // 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...
1633 #ifndef ID3DXBuffer_GetBufferPointer
1634 #if !defined(__cplusplus) || defined(CINTERFACE)
1635 #define ID3DXBuffer_GetBufferPointer(p) (p)->lpVtbl->GetBufferPointer(p)
1636 #define ID3DXBuffer_GetBufferSize(p) (p)->lpVtbl->GetBufferSize(p)
1637 #define ID3DXBuffer_Release(p) (p)->lpVtbl->Release(p)
1639 #define ID3DXBuffer_GetBufferPointer(p) (p)->GetBufferPointer()
1640 #define ID3DXBuffer_GetBufferSize(p) (p)->GetBufferSize()
1641 #define ID3DXBuffer_Release(p) (p)->Release()
1644 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1646 DWORD shaderflags = 0;
1648 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1649 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1650 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1651 if (vertstring && vertstring[0])
1655 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1656 vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1659 vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1662 vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1663 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1664 memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1665 ID3DXBuffer_Release(vsbuffer);
1669 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1670 Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1671 ID3DXBuffer_Release(vslog);
1674 if (fragstring && fragstring[0])
1678 FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1679 psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1682 psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1685 psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1686 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1687 memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1688 ID3DXBuffer_Release(psbuffer);
1692 strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1693 Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1694 ID3DXBuffer_Release(pslog);
1697 Sys_UnloadLibrary(&d3dx9_dll);
1700 Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1704 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1705 if (FAILED(vsresult))
1706 Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1707 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1708 if (FAILED(psresult))
1709 Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1711 // free the shader data
1712 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1713 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1716 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, dpuint64 permutation)
1719 shadermodeinfo_t *modeinfo = &shadermodeinfo[SHADERLANGUAGE_HLSL][mode];
1720 int vertstring_length = 0;
1721 int geomstring_length = 0;
1722 int fragstring_length = 0;
1725 char *vertstring, *geomstring, *fragstring;
1726 char permutationname[256];
1727 char cachename[256];
1728 int vertstrings_count = 0;
1729 int geomstrings_count = 0;
1730 int fragstrings_count = 0;
1731 const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1732 const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1733 const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1738 p->vertexshader = NULL;
1739 p->pixelshader = NULL;
1741 permutationname[0] = 0;
1743 sourcestring = ShaderModeInfo_GetShaderText(modeinfo, true, false);
1745 strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1746 strlcat(cachename, "hlsl/", sizeof(cachename));
1748 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1749 vertstrings_count = 0;
1750 geomstrings_count = 0;
1751 fragstrings_count = 0;
1752 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1753 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1754 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1756 // the first pretext is which type of shader to compile as
1757 // (later these will all be bound together as a program object)
1758 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1759 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1760 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1762 // the second pretext is the mode (for example a light source)
1763 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1764 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1765 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1766 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1767 strlcat(cachename, modeinfo->name, sizeof(cachename));
1769 // now add all the permutation pretexts
1770 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1772 if (permutation & (1ll<<i))
1774 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1775 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1776 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1777 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1778 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1782 // keep line numbers correct
1783 vertstrings_list[vertstrings_count++] = "\n";
1784 geomstrings_list[geomstrings_count++] = "\n";
1785 fragstrings_list[fragstrings_count++] = "\n";
1790 R_CompileShader_AddStaticParms(mode, permutation);
1791 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1792 vertstrings_count += shaderstaticparms_count;
1793 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1794 geomstrings_count += shaderstaticparms_count;
1795 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1796 fragstrings_count += shaderstaticparms_count;
1798 // replace spaces in the cachename with _ characters
1799 for (i = 0;cachename[i];i++)
1800 if (cachename[i] == ' ')
1803 // now append the shader text itself
1804 vertstrings_list[vertstrings_count++] = sourcestring;
1805 geomstrings_list[geomstrings_count++] = sourcestring;
1806 fragstrings_list[fragstrings_count++] = sourcestring;
1808 vertstring_length = 0;
1809 for (i = 0;i < vertstrings_count;i++)
1810 vertstring_length += (int)strlen(vertstrings_list[i]);
1811 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1812 for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1813 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1815 geomstring_length = 0;
1816 for (i = 0;i < geomstrings_count;i++)
1817 geomstring_length += (int)strlen(geomstrings_list[i]);
1818 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1819 for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1820 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1822 fragstring_length = 0;
1823 for (i = 0;i < fragstrings_count;i++)
1824 fragstring_length += (int)strlen(fragstrings_list[i]);
1825 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1826 for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1827 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1829 // try to load the cached shader, or generate one
1830 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1832 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1833 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1835 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1839 Mem_Free(vertstring);
1841 Mem_Free(geomstring);
1843 Mem_Free(fragstring);
1845 Mem_Free(sourcestring);
1848 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1849 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1850 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);}
1851 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);}
1852 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);}
1853 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);}
1855 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1856 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1857 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);}
1858 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);}
1859 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);}
1860 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);}
1862 void R_SetupShader_SetPermutationHLSL(unsigned int mode, dpuint64 permutation)
1864 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1865 if (r_hlsl_permutation != perm)
1867 r_hlsl_permutation = perm;
1868 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1870 if (!r_hlsl_permutation->compiled)
1871 R_HLSL_CompilePermutation(perm, mode, permutation);
1872 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1874 // remove features until we find a valid permutation
1876 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1878 // reduce i more quickly whenever it would not remove any bits
1879 dpuint64 j = 1ll<<(SHADERPERMUTATION_COUNT-1-i);
1880 if (!(permutation & j))
1883 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1884 if (!r_hlsl_permutation->compiled)
1885 R_HLSL_CompilePermutation(perm, mode, permutation);
1886 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1889 if (i >= SHADERPERMUTATION_COUNT)
1891 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1892 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1893 return; // no bit left to clear, entire mode is broken
1897 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1898 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1900 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1901 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1902 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1906 static void R_SetupShader_SetPermutationSoft(unsigned int mode, dpuint64 permutation)
1908 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1909 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1910 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1911 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1914 void R_GLSL_Restart_f(void)
1916 unsigned int i, limit;
1917 switch(vid.renderpath)
1919 case RENDERPATH_D3D9:
1922 r_hlsl_permutation_t *p;
1923 r_hlsl_permutation = NULL;
1924 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1925 for (i = 0;i < limit;i++)
1927 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1929 if (p->vertexshader)
1930 IDirect3DVertexShader9_Release(p->vertexshader);
1932 IDirect3DPixelShader9_Release(p->pixelshader);
1933 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1936 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1940 case RENDERPATH_D3D10:
1941 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1943 case RENDERPATH_D3D11:
1944 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1946 case RENDERPATH_GL20:
1947 case RENDERPATH_GLES2:
1949 r_glsl_permutation_t *p;
1950 r_glsl_permutation = NULL;
1951 limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1952 for (i = 0;i < limit;i++)
1954 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1956 GL_Backend_FreeProgram(p->program);
1957 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1960 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1963 case RENDERPATH_GL11:
1964 case RENDERPATH_GL13:
1965 case RENDERPATH_GLES1:
1967 case RENDERPATH_SOFT:
1972 static void R_GLSL_DumpShader_f(void)
1974 int i, language, mode, dupe;
1976 shadermodeinfo_t *modeinfo;
1979 for (language = 0;language < SHADERLANGUAGE_COUNT;language++)
1981 modeinfo = shadermodeinfo[language];
1982 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1984 // don't dump the same file multiple times (most or all shaders come from the same file)
1985 for (dupe = mode - 1;dupe >= 0;dupe--)
1986 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1990 text = modeinfo[mode].builtinstring;
1993 file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1996 FS_Print(file, "/* The engine may define the following macros:\n");
1997 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1998 for (i = 0;i < SHADERMODE_COUNT;i++)
1999 FS_Print(file, modeinfo[i].pretext);
2000 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
2001 FS_Print(file, shaderpermutationinfo[i].pretext);
2002 FS_Print(file, "*/\n");
2003 FS_Print(file, text);
2005 Con_Printf("%s written\n", modeinfo[mode].filename);
2008 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2013 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2015 dpuint64 permutation = 0;
2016 if (r_trippy.integer && !notrippy)
2017 permutation |= SHADERPERMUTATION_TRIPPY;
2018 permutation |= SHADERPERMUTATION_VIEWTINT;
2020 permutation |= SHADERPERMUTATION_DIFFUSE;
2022 permutation |= SHADERPERMUTATION_SPECULAR;
2023 if (texturemode == GL_MODULATE)
2024 permutation |= SHADERPERMUTATION_COLORMAPPING;
2025 else if (texturemode == GL_ADD)
2026 permutation |= SHADERPERMUTATION_GLOW;
2027 else if (texturemode == GL_DECAL)
2028 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2029 if (usegamma && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2030 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2031 if (suppresstexalpha)
2032 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2034 texturemode = GL_MODULATE;
2035 if (vid.allowalphatocoverage)
2036 GL_AlphaToCoverage(false);
2037 switch (vid.renderpath)
2039 case RENDERPATH_D3D9:
2041 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2042 R_Mesh_TexBind(GL20TU_FIRST , first );
2043 R_Mesh_TexBind(GL20TU_SECOND, second);
2044 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2045 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps);
2048 case RENDERPATH_D3D10:
2049 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051 case RENDERPATH_D3D11:
2052 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2054 case RENDERPATH_GL20:
2055 case RENDERPATH_GLES2:
2056 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2057 if (r_glsl_permutation->tex_Texture_First >= 0)
2058 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2059 if (r_glsl_permutation->tex_Texture_Second >= 0)
2060 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2061 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2062 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2064 case RENDERPATH_GL13:
2065 case RENDERPATH_GLES1:
2066 R_Mesh_TexBind(0, first );
2067 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2068 R_Mesh_TexMatrix(0, NULL);
2069 R_Mesh_TexBind(1, second);
2072 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2073 R_Mesh_TexMatrix(1, NULL);
2076 case RENDERPATH_GL11:
2077 R_Mesh_TexBind(0, first );
2078 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2079 R_Mesh_TexMatrix(0, NULL);
2081 case RENDERPATH_SOFT:
2082 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2083 R_Mesh_TexBind(GL20TU_FIRST , first );
2084 R_Mesh_TexBind(GL20TU_SECOND, second);
2089 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2091 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2094 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2096 dpuint64 permutation = 0;
2097 if (r_trippy.integer && !notrippy)
2098 permutation |= SHADERPERMUTATION_TRIPPY;
2100 permutation |= SHADERPERMUTATION_DEPTHRGB;
2102 permutation |= SHADERPERMUTATION_SKELETAL;
2104 if (vid.allowalphatocoverage)
2105 GL_AlphaToCoverage(false);
2106 switch (vid.renderpath)
2108 case RENDERPATH_D3D9:
2110 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2113 case RENDERPATH_D3D10:
2114 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2116 case RENDERPATH_D3D11:
2117 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2119 case RENDERPATH_GL20:
2120 case RENDERPATH_GLES2:
2121 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2122 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2123 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);
2126 case RENDERPATH_GL13:
2127 case RENDERPATH_GLES1:
2128 R_Mesh_TexBind(0, 0);
2129 R_Mesh_TexBind(1, 0);
2131 case RENDERPATH_GL11:
2132 R_Mesh_TexBind(0, 0);
2134 case RENDERPATH_SOFT:
2135 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2140 #define BLENDFUNC_ALLOWS_COLORMOD 1
2141 #define BLENDFUNC_ALLOWS_FOG 2
2142 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2143 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2144 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2145 static int R_BlendFuncFlags(int src, int dst)
2149 // a blendfunc allows colormod if:
2150 // a) it can never keep the destination pixel invariant, or
2151 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2152 // this is to prevent unintended side effects from colormod
2154 // a blendfunc allows fog if:
2155 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2156 // this is to prevent unintended side effects from fog
2158 // these checks are the output of fogeval.pl
2160 r |= BLENDFUNC_ALLOWS_COLORMOD;
2161 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2162 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2163 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2164 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2165 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2167 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2169 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2170 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2171 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2172 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2173 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2174 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2176 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2177 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2179 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2180 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2181 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2186 void R_SetupShader_Surface(const float rtlightambient[3], const float rtlightdiffuse[3], const float rtlightspecular[3], rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2188 // select a permutation of the lighting shader appropriate to this
2189 // combination of texture, entity, light source, and fogging, only use the
2190 // minimum features necessary to avoid wasting rendering time in the
2191 // fragment shader on features that are not being used
2192 dpuint64 permutation = 0;
2193 unsigned int mode = 0;
2195 texture_t *t = rsurface.texture;
2197 matrix4x4_t tempmatrix;
2198 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2199 if (r_trippy.integer && !notrippy)
2200 permutation |= SHADERPERMUTATION_TRIPPY;
2201 if (t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2202 permutation |= SHADERPERMUTATION_ALPHAKILL;
2203 if (t->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2204 permutation |= SHADERPERMUTATION_OCCLUDE;
2205 if (t->r_water_waterscroll[0] && t->r_water_waterscroll[1])
2206 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2207 if (rsurfacepass == RSURFPASS_BACKGROUND)
2209 // distorted background
2210 if (t->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2212 mode = SHADERMODE_WATER;
2213 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2214 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2215 if((r_wateralpha.value < 1) && (t->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2217 // this is the right thing to do for wateralpha
2218 GL_BlendFunc(GL_ONE, GL_ZERO);
2219 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2223 // this is the right thing to do for entity alpha
2224 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2225 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228 else if (t->currentmaterialflags & MATERIALFLAG_REFRACTION)
2230 mode = SHADERMODE_REFRACTION;
2231 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2232 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2233 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2234 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238 mode = SHADERMODE_GENERIC;
2239 permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2240 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2243 if (vid.allowalphatocoverage)
2244 GL_AlphaToCoverage(false);
2246 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2248 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2250 switch(t->offsetmapping)
2252 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2253 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2254 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255 case OFFSETMAPPING_OFF: break;
2258 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2259 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2260 // normalmap (deferred prepass), may use alpha test on diffuse
2261 mode = SHADERMODE_DEFERREDGEOMETRY;
2262 GL_BlendFunc(GL_ONE, GL_ZERO);
2263 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2264 if (vid.allowalphatocoverage)
2265 GL_AlphaToCoverage(false);
2267 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2269 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2271 switch(t->offsetmapping)
2273 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2274 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2275 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2276 case OFFSETMAPPING_OFF: break;
2279 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2280 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2281 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2282 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2284 mode = SHADERMODE_LIGHTSOURCE;
2285 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2286 permutation |= SHADERPERMUTATION_CUBEFILTER;
2287 if (VectorLength2(rtlightdiffuse) > 0)
2288 permutation |= SHADERPERMUTATION_DIFFUSE;
2289 if (VectorLength2(rtlightspecular) > 0)
2290 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2291 if (r_refdef.fogenabled)
2292 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2293 if (t->colormapping)
2294 permutation |= SHADERPERMUTATION_COLORMAPPING;
2295 if (r_shadow_usingshadowmap2d)
2297 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2298 if(r_shadow_shadowmapvsdct)
2299 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2301 if (r_shadow_shadowmap2ddepthbuffer)
2302 permutation |= SHADERPERMUTATION_DEPTHRGB;
2304 if (t->reflectmasktexture)
2305 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2306 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2307 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2308 if (vid.allowalphatocoverage)
2309 GL_AlphaToCoverage(false);
2311 else if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2313 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2315 switch(t->offsetmapping)
2317 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2318 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2319 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2320 case OFFSETMAPPING_OFF: break;
2323 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2324 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2325 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2326 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2327 // directional model lighting
2328 mode = SHADERMODE_LIGHTDIRECTION;
2329 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2330 permutation |= SHADERPERMUTATION_GLOW;
2331 if (VectorLength2(t->render_modellight_diffuse))
2332 permutation |= SHADERPERMUTATION_DIFFUSE;
2333 if (VectorLength2(t->render_modellight_specular) > 0)
2334 permutation |= SHADERPERMUTATION_SPECULAR;
2335 if (r_refdef.fogenabled)
2336 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2337 if (t->colormapping)
2338 permutation |= SHADERPERMUTATION_COLORMAPPING;
2339 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2341 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2342 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2344 if (r_shadow_shadowmap2ddepthbuffer)
2345 permutation |= SHADERPERMUTATION_DEPTHRGB;
2347 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2348 permutation |= SHADERPERMUTATION_REFLECTION;
2349 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2350 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2351 if (t->reflectmasktexture)
2352 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2353 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2355 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2356 if (r_shadow_bouncegrid_state.directional)
2357 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2359 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2360 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2361 // when using alphatocoverage, we don't need alphakill
2362 if (vid.allowalphatocoverage)
2364 if (r_transparent_alphatocoverage.integer)
2366 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2367 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2370 GL_AlphaToCoverage(false);
2375 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(t->nmaptexture) & TEXF_ALPHA) || t->offsetbias != 0.0f))
2377 switch(t->offsetmapping)
2379 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2380 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2381 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2382 case OFFSETMAPPING_OFF: break;
2385 if (t->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2386 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2387 if (t->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2388 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2390 if ((t->glowtexture || t->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2391 permutation |= SHADERPERMUTATION_GLOW;
2392 if (r_refdef.fogenabled)
2393 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2394 if (t->colormapping)
2395 permutation |= SHADERPERMUTATION_COLORMAPPING;
2396 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2398 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2399 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2401 if (r_shadow_shadowmap2ddepthbuffer)
2402 permutation |= SHADERPERMUTATION_DEPTHRGB;
2404 if (t->currentmaterialflags & MATERIALFLAG_REFLECTION)
2405 permutation |= SHADERPERMUTATION_REFLECTION;
2406 if (r_shadow_usingdeferredprepass && !(t->currentmaterialflags & MATERIALFLAG_BLENDED))
2407 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2408 if (t->reflectmasktexture)
2409 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2410 if (FAKELIGHT_ENABLED)
2412 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2413 mode = SHADERMODE_FAKELIGHT;
2414 permutation |= SHADERPERMUTATION_DIFFUSE;
2415 if (VectorLength2(t->render_lightmap_specular) > 0)
2416 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2418 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2420 // deluxemapping (light direction texture)
2421 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2422 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2424 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2425 permutation |= SHADERPERMUTATION_DIFFUSE;
2426 if (VectorLength2(t->render_lightmap_specular) > 0)
2427 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2429 else if (r_glsl_deluxemapping.integer >= 2)
2431 // fake deluxemapping (uniform light direction in tangentspace)
2432 if (rsurface.uselightmaptexture)
2433 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2435 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2436 permutation |= SHADERPERMUTATION_DIFFUSE;
2437 if (VectorLength2(t->render_lightmap_specular) > 0)
2438 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2440 else if (rsurface.uselightmaptexture)
2442 // ordinary lightmapping (q1bsp, q3bsp)
2443 mode = SHADERMODE_LIGHTMAP;
2447 // ordinary vertex coloring (q3bsp)
2448 mode = SHADERMODE_VERTEXCOLOR;
2450 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2452 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2453 if (r_shadow_bouncegrid_state.directional)
2454 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2456 GL_BlendFunc(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2457 blendfuncflags = R_BlendFuncFlags(t->currentlayers[0].blendfunc1, t->currentlayers[0].blendfunc2);
2458 // when using alphatocoverage, we don't need alphakill
2459 if (vid.allowalphatocoverage)
2461 if (r_transparent_alphatocoverage.integer)
2463 GL_AlphaToCoverage((t->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2464 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2467 GL_AlphaToCoverage(false);
2470 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2471 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2472 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2473 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2474 switch(vid.renderpath)
2476 case RENDERPATH_D3D9:
2478 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);
2479 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2480 R_SetupShader_SetPermutationHLSL(mode, permutation);
2481 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2482 if (mode == SHADERMODE_LIGHTSOURCE)
2484 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2485 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2489 if (mode == SHADERMODE_LIGHTDIRECTION)
2491 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2494 Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2495 Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2496 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2497 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2498 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2500 if (mode == SHADERMODE_LIGHTSOURCE)
2502 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2503 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2504 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2505 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2506 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2508 // additive passes are only darkened by fog, not tinted
2509 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2510 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2514 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2516 if (mode == SHADERMODE_FLATCOLOR)
2518 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2520 else if (mode == SHADERMODE_LIGHTDIRECTION)
2522 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2524 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, 1, 1, 1); // DEPRECATED
2526 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2530 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2531 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2532 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2534 // additive passes are only darkened by fog, not tinted
2535 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2536 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2539 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2540 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2541 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2542 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2543 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2544 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, t->reflectmax - t->reflectmin);
2545 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, t->reflectmin);
2546 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (t->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2547 if (mode == SHADERMODE_WATER)
2548 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2550 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2552 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_modelshadowmap_texturescale[0], r_shadow_modelshadowmap_texturescale[1], r_shadow_modelshadowmap_texturescale[2], r_shadow_modelshadowmap_texturescale[3]);
2553 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_modelshadowmap_parameters[0], r_shadow_modelshadowmap_parameters[1], r_shadow_modelshadowmap_parameters[2], r_shadow_modelshadowmap_parameters[3]);
2557 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
2558 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
2560 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2561 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2562 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2563 if (t->pantstexture)
2564 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2566 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2567 if (t->shirttexture)
2568 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2570 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2571 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2572 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2573 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2574 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2575 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2576 r_glsl_offsetmapping_scale.value*t->offsetscale,
2577 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2578 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2579 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2581 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2582 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, t->offsetbias);
2583 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2584 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2586 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2587 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2588 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2589 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2590 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2591 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2592 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2593 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2594 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2595 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2596 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2597 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2598 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2599 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2600 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2601 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2602 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2603 if (rsurfacepass == RSURFPASS_BACKGROUND)
2605 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2606 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2607 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2611 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2613 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2614 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2615 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2616 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2618 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2619 if (rsurface.rtlight)
2621 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2622 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2627 case RENDERPATH_D3D10:
2628 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2630 case RENDERPATH_D3D11:
2631 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2633 case RENDERPATH_GL20:
2634 case RENDERPATH_GLES2:
2635 if (!vid.useinterleavedarrays)
2637 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);
2638 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2639 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2640 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2641 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2642 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2643 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2644 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2645 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2646 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2647 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2651 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);
2652 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2654 // this has to be after RSurf_PrepareVerticesForBatch
2655 if (rsurface.batchskeletaltransform3x4buffer)
2656 permutation |= SHADERPERMUTATION_SKELETAL;
2657 R_SetupShader_SetPermutationGLSL(mode, permutation);
2658 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2659 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);
2661 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2662 if (mode == SHADERMODE_LIGHTSOURCE)
2664 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2665 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2666 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2667 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2668 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2669 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2671 // additive passes are only darkened by fog, not tinted
2672 if (r_glsl_permutation->loc_FogColor >= 0)
2673 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2674 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2678 if (mode == SHADERMODE_FLATCOLOR)
2680 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2682 else if (mode == SHADERMODE_LIGHTDIRECTION)
2684 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2685 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2686 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2687 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2688 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2689 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, 1, 1, 1); // DEPRECATED
2690 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2694 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2695 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2696 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2697 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2698 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2700 // additive passes are only darkened by fog, not tinted
2701 if (r_glsl_permutation->loc_FogColor >= 0)
2703 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2704 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2706 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2708 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2709 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]);
2710 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]);
2711 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2712 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2713 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, t->reflectmax - t->reflectmin);
2714 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, t->reflectmin);
2715 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2716 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2718 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2719 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2720 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2721 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2723 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]);
2724 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]);
2728 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]);
2729 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]);
2732 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2733 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2734 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2735 if (r_glsl_permutation->loc_Color_Pants >= 0)
2737 if (t->pantstexture)
2738 qglUniform3f(r_glsl_permutation->loc_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2740 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2742 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2744 if (t->shirttexture)
2745 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2747 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2749 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]);
2750 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2751 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2752 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2753 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2754 r_glsl_offsetmapping_scale.value*t->offsetscale,
2755 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2756 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2757 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2759 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);
2760 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, t->offsetbias);
2761 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]);
2762 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2763 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);}
2764 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2766 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2767 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2768 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2769 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , t->nmaptexture );
2770 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , t->basetexture );
2771 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , t->glosstexture );
2772 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , t->glowtexture );
2773 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , t->backgroundnmaptexture );
2774 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , t->backgroundbasetexture );
2775 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , t->backgroundglosstexture );
2776 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , t->backgroundglowtexture );
2777 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , t->pantstexture );
2778 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , t->shirttexture );
2779 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , t->reflectmasktexture );
2780 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2781 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2782 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2783 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2784 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2785 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2786 if (rsurfacepass == RSURFPASS_BACKGROUND)
2788 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2789 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2790 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2794 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2796 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2797 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2798 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2799 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2801 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture );
2802 if (rsurface.rtlight)
2804 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2805 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2808 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2811 case RENDERPATH_GL11:
2812 case RENDERPATH_GL13:
2813 case RENDERPATH_GLES1:
2815 case RENDERPATH_SOFT:
2816 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);
2817 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2818 R_SetupShader_SetPermutationSoft(mode, permutation);
2819 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2820 if (mode == SHADERMODE_LIGHTSOURCE)
2822 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2823 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2824 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2825 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, rtlightambient[0], rtlightambient[1], rtlightambient[2]);
2826 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rtlightdiffuse[0], rtlightdiffuse[1], rtlightdiffuse[2]);
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, rtlightspecular[0], rtlightspecular[1], rtlightspecular[2]);
2829 // additive passes are only darkened by fog, not tinted
2830 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2831 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2835 if (mode == SHADERMODE_FLATCOLOR)
2837 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2839 else if (mode == SHADERMODE_LIGHTDIRECTION)
2841 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_modellight_ambient[0], t->render_modellight_ambient[1], t->render_modellight_ambient[2]);
2842 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_modellight_diffuse[0], t->render_modellight_diffuse[1], t->render_modellight_diffuse[2]);
2843 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_modellight_specular[0], t->render_modellight_specular[1], t->render_modellight_specular[2]);
2844 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, 1, 1, 1); // DEPRECATED
2845 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, t->render_modellight_lightdir[0], t->render_modellight_lightdir[1], t->render_modellight_lightdir[2]);
2849 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2]);
2850 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2]);
2851 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, t->render_lightmap_specular[0], t->render_lightmap_specular[1], t->render_lightmap_specular[2]);
2853 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, t->render_rtlight_diffuse[0], t->render_rtlight_diffuse[1], t->render_rtlight_diffuse[2]);
2854 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, t->render_rtlight_specular[0], t->render_rtlight_specular[1], t->render_rtlight_specular[2]);
2855 // additive passes are only darkened by fog, not tinted
2856 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2857 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2859 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2860 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * t->refractfactor, r_water_refractdistort.value * t->refractfactor, r_water_reflectdistort.value * t->reflectfactor, r_water_reflectdistort.value * t->reflectfactor);
2861 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]);
2862 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]);
2863 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, t->refractcolor4f[0], t->refractcolor4f[1], t->refractcolor4f[2], t->refractcolor4f[3] * t->currentalpha);
2864 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, t->reflectcolor4f[0], t->reflectcolor4f[1], t->reflectcolor4f[2], t->reflectcolor4f[3] * t->currentalpha);
2865 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, t->reflectmax - t->reflectmin);
2866 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, t->reflectmin);
2867 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, t->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2868 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, t->r_water_waterscroll[0], t->r_water_waterscroll[1]);
2870 {Matrix4x4_ToArrayFloatGL(&t->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2871 {Matrix4x4_ToArrayFloatGL(&t->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2872 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2873 if (permutation & SHADERPERMUTATION_SHADOWMAPORTHO)
2875 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]);
2876 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]);
2880 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]);
2881 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]);
2884 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2]);
2885 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, t->currentalpha * ((t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? t->r_water_wateralpha : 1));
2886 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2887 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2889 if (t->pantstexture)
2890 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, t->render_colormap_pants[0], t->render_colormap_pants[1], t->render_colormap_pants[2]);
2892 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2894 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2896 if (t->shirttexture)
2897 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, t->render_colormap_shirt[0], t->render_colormap_shirt[1], t->render_colormap_shirt[2]);
2899 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2901 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2902 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2903 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2904 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2905 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2906 r_glsl_offsetmapping_scale.value*t->offsetscale,
2907 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2908 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2909 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2911 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2912 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, t->offsetbias);
2913 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2916 R_Mesh_TexBind(GL20TU_NORMAL , t->nmaptexture );
2917 R_Mesh_TexBind(GL20TU_COLOR , t->basetexture );
2918 R_Mesh_TexBind(GL20TU_GLOSS , t->glosstexture );
2919 R_Mesh_TexBind(GL20TU_GLOW , t->glowtexture );
2920 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , t->backgroundnmaptexture );
2921 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , t->backgroundbasetexture );
2922 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , t->backgroundglosstexture );
2923 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , t->backgroundglowtexture );
2924 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , t->pantstexture );
2925 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , t->shirttexture );
2926 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , t->reflectmasktexture );
2927 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , t->reflectcubetexture ? t->reflectcubetexture : r_texture_whitecube);
2928 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2929 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2930 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2931 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2932 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2933 if (rsurfacepass == RSURFPASS_BACKGROUND)
2935 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->rt_refraction ? waterplane->rt_refraction->colortexture[0] : r_texture_black);
2936 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->rt_camera ? waterplane->rt_camera->colortexture[0] : r_texture_black);
2937 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2941 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->rt_reflection ? waterplane->rt_reflection->colortexture[0] : r_texture_black);
2943 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2944 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2945 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2946 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2948 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2949 if (rsurface.rtlight)
2951 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2952 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2959 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2961 // select a permutation of the lighting shader appropriate to this
2962 // combination of texture, entity, light source, and fogging, only use the
2963 // minimum features necessary to avoid wasting rendering time in the
2964 // fragment shader on features that are not being used
2965 dpuint64 permutation = 0;
2966 unsigned int mode = 0;
2967 const float *lightcolorbase = rtlight->currentcolor;
2968 float ambientscale = rtlight->ambientscale;
2969 float diffusescale = rtlight->diffusescale;
2970 float specularscale = rtlight->specularscale;
2971 // this is the location of the light in view space
2972 vec3_t viewlightorigin;
2973 // this transforms from view space (camera) to light space (cubemap)
2974 matrix4x4_t viewtolight;
2975 matrix4x4_t lighttoview;
2976 float viewtolight16f[16];
2978 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2979 if (rtlight->currentcubemap != r_texture_whitecube)
2980 permutation |= SHADERPERMUTATION_CUBEFILTER;
2981 if (diffusescale > 0)
2982 permutation |= SHADERPERMUTATION_DIFFUSE;
2983 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2984 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2985 if (r_shadow_usingshadowmap2d)
2987 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2988 if (r_shadow_shadowmapvsdct)
2989 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2991 if (r_shadow_shadowmap2ddepthbuffer)
2992 permutation |= SHADERPERMUTATION_DEPTHRGB;
2994 if (vid.allowalphatocoverage)
2995 GL_AlphaToCoverage(false);
2996 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2997 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2998 Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
2999 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3000 switch(vid.renderpath)
3002 case RENDERPATH_D3D9:
3004 R_SetupShader_SetPermutationHLSL(mode, permutation);
3005 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3006 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3007 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3008 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3009 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3010 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_lightshadowmap_texturescale[0], r_shadow_lightshadowmap_texturescale[1], r_shadow_lightshadowmap_texturescale[2], r_shadow_lightshadowmap_texturescale[3]);
3011 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_lightshadowmap_parameters[0], r_shadow_lightshadowmap_parameters[1], r_shadow_lightshadowmap_parameters[2], r_shadow_lightshadowmap_parameters[3]);
3012 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);
3013 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3014 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3016 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3017 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3018 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3019 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3020 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3023 case RENDERPATH_D3D10:
3024 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3026 case RENDERPATH_D3D11:
3027 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3029 case RENDERPATH_GL20:
3030 case RENDERPATH_GLES2:
3031 R_SetupShader_SetPermutationGLSL(mode, permutation);
3032 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
3034 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3035 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3036 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3037 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]);
3038 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]);
3039 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);
3040 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]);
3041 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
3043 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
3044 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
3045 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
3046 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2ddepthtexture );
3047 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
3049 case RENDERPATH_GL11:
3050 case RENDERPATH_GL13:
3051 case RENDERPATH_GLES1:
3053 case RENDERPATH_SOFT:
3054 R_SetupShader_SetPermutationGLSL(mode, permutation);
3055 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3056 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
3057 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3058 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3059 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3060 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]);
3061 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]);
3062 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);
3063 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3064 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3066 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3067 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3068 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3069 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2ddepthtexture );
3070 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3075 #define SKINFRAME_HASH 1024
3079 unsigned int loadsequence; // incremented each level change
3080 memexpandablearray_t array;
3081 skinframe_t *hash[SKINFRAME_HASH];
3084 r_skinframe_t r_skinframe;
3086 void R_SkinFrame_PrepareForPurge(void)
3088 r_skinframe.loadsequence++;
3089 // wrap it without hitting zero
3090 if (r_skinframe.loadsequence >= 200)
3091 r_skinframe.loadsequence = 1;
3094 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3098 // mark the skinframe as used for the purging code
3099 skinframe->loadsequence = r_skinframe.loadsequence;
3102 void R_SkinFrame_PurgeSkinFrame(skinframe_t *s)
3104 if (s->merged == s->base)
3106 R_PurgeTexture(s->stain); s->stain = NULL;
3107 R_PurgeTexture(s->merged); s->merged = NULL;
3108 R_PurgeTexture(s->base); s->base = NULL;
3109 R_PurgeTexture(s->pants); s->pants = NULL;
3110 R_PurgeTexture(s->shirt); s->shirt = NULL;
3111 R_PurgeTexture(s->nmap); s->nmap = NULL;
3112 R_PurgeTexture(s->gloss); s->gloss = NULL;
3113 R_PurgeTexture(s->glow); s->glow = NULL;
3114 R_PurgeTexture(s->fog); s->fog = NULL;
3115 R_PurgeTexture(s->reflect); s->reflect = NULL;
3116 s->loadsequence = 0;
3119 void R_SkinFrame_Purge(void)
3123 for (i = 0;i < SKINFRAME_HASH;i++)
3125 for (s = r_skinframe.hash[i];s;s = s->next)
3127 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3128 R_SkinFrame_PurgeSkinFrame(s);
3133 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3135 char basename[MAX_QPATH];
3137 Image_StripImageExtension(name, basename, sizeof(basename));
3139 if( last == NULL ) {
3141 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3142 item = r_skinframe.hash[hashindex];
3147 // linearly search through the hash bucket
3148 for( ; item ; item = item->next ) {
3149 if( !strcmp( item->basename, basename ) ) {
3156 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3160 char basename[MAX_QPATH];
3162 Image_StripImageExtension(name, basename, sizeof(basename));
3164 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3165 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3166 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3173 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3174 memset(item, 0, sizeof(*item));
3175 strlcpy(item->basename, basename, sizeof(item->basename));
3176 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3177 item->comparewidth = comparewidth;
3178 item->compareheight = compareheight;
3179 item->comparecrc = comparecrc;
3180 item->next = r_skinframe.hash[hashindex];
3181 r_skinframe.hash[hashindex] = item;
3183 else if (textureflags & TEXF_FORCE_RELOAD)
3187 R_SkinFrame_PurgeSkinFrame(item);
3190 R_SkinFrame_MarkUsed(item);
3194 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3196 unsigned long long avgcolor[5], wsum; \
3204 for(pix = 0; pix < cnt; ++pix) \
3207 for(comp = 0; comp < 3; ++comp) \
3209 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3212 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3214 for(comp = 0; comp < 3; ++comp) \
3215 avgcolor[comp] += getpixel * w; \
3218 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3219 avgcolor[4] += getpixel; \
3221 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3223 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3224 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3225 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3226 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3229 extern cvar_t gl_picmip;
3230 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain, qboolean fallbacknotexture)
3233 unsigned char *pixels;
3234 unsigned char *bumppixels;
3235 unsigned char *basepixels = NULL;
3236 int basepixels_width = 0;
3237 int basepixels_height = 0;
3238 skinframe_t *skinframe;
3239 rtexture_t *ddsbase = NULL;
3240 qboolean ddshasalpha = false;
3241 float ddsavgcolor[4];
3242 char basename[MAX_QPATH];
3243 int miplevel = R_PicmipForFlags(textureflags);
3244 int savemiplevel = miplevel;
3248 if (cls.state == ca_dedicated)
3251 // return an existing skinframe if already loaded
3252 // if loading of the first image fails, don't make a new skinframe as it
3253 // would cause all future lookups of this to be missing
3254 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3255 if (skinframe && skinframe->base)
3258 Image_StripImageExtension(name, basename, sizeof(basename));
3260 // check for DDS texture file first
3261 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3263 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3264 if (basepixels == NULL && fallbacknotexture)
3265 basepixels = Image_GenerateNoTexture();
3266 if (basepixels == NULL)
3270 // FIXME handle miplevel
3272 if (developer_loading.integer)
3273 Con_Printf("loading skin \"%s\"\n", name);
3275 // we've got some pixels to store, so really allocate this new texture now
3277 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3278 textureflags &= ~TEXF_FORCE_RELOAD;
3279 skinframe->stain = NULL;
3280 skinframe->merged = NULL;
3281 skinframe->base = NULL;
3282 skinframe->pants = NULL;
3283 skinframe->shirt = NULL;
3284 skinframe->nmap = NULL;
3285 skinframe->gloss = NULL;
3286 skinframe->glow = NULL;
3287 skinframe->fog = NULL;
3288 skinframe->reflect = NULL;
3289 skinframe->hasalpha = false;
3290 // we could store the q2animname here too
3294 skinframe->base = ddsbase;
3295 skinframe->hasalpha = ddshasalpha;
3296 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3297 if (r_loadfog && skinframe->hasalpha)
3298 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);
3299 //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]);
3303 basepixels_width = image_width;
3304 basepixels_height = image_height;
3305 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);
3306 if (textureflags & TEXF_ALPHA)
3308 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3310 if (basepixels[j] < 255)
3312 skinframe->hasalpha = true;
3316 if (r_loadfog && skinframe->hasalpha)
3318 // has transparent pixels
3319 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3320 for (j = 0;j < image_width * image_height * 4;j += 4)
3325 pixels[j+3] = basepixels[j+3];
3327 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);
3331 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3333 //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]);
3334 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3335 R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3336 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3337 R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3343 mymiplevel = savemiplevel;
3344 if (r_loadnormalmap)
3345 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);
3346 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3348 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3349 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3350 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3351 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3354 // _norm is the name used by tenebrae and has been adopted as standard
3355 if (r_loadnormalmap && skinframe->nmap == NULL)
3357 mymiplevel = savemiplevel;
3358 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3360 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);
3364 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3366 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3367 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3368 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);
3370 Mem_Free(bumppixels);
3372 else if (r_shadow_bumpscale_basetexture.value > 0)
3374 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3375 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3376 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);
3380 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3381 R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3385 // _luma is supported only for tenebrae compatibility
3386 // _glow is the preferred name
3387 mymiplevel = savemiplevel;
3388 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))))
3390 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);
3392 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3393 R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3395 Mem_Free(pixels);pixels = NULL;
3398 mymiplevel = savemiplevel;
3399 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3401 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);
3403 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3404 R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3410 mymiplevel = savemiplevel;
3411 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3413 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);
3415 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3416 R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3422 mymiplevel = savemiplevel;
3423 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3425 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);
3427 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3428 R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3434 mymiplevel = savemiplevel;
3435 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3437 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);
3439 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3440 R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447 Mem_Free(basepixels);
3452 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3453 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3456 skinframe_t *skinframe;
3459 if (cls.state == ca_dedicated)
3462 // if already loaded just return it, otherwise make a new skinframe
3463 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3464 if (skinframe->base)
3466 textureflags &= ~TEXF_FORCE_RELOAD;
3468 skinframe->stain = NULL;
3469 skinframe->merged = NULL;
3470 skinframe->base = NULL;
3471 skinframe->pants = NULL;
3472 skinframe->shirt = NULL;
3473 skinframe->nmap = NULL;
3474 skinframe->gloss = NULL;
3475 skinframe->glow = NULL;
3476 skinframe->fog = NULL;
3477 skinframe->reflect = NULL;
3478 skinframe->hasalpha = false;
3480 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3484 if (developer_loading.integer)
3485 Con_Printf("loading 32bit skin \"%s\"\n", name);
3487 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3489 unsigned char *a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3490 unsigned char *b = a + width * height * 4;
3491 Image_HeightmapToNormalmap_BGRA(skindata, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3492 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);
3495 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3496 if (textureflags & TEXF_ALPHA)
3498 for (i = 3;i < width * height * 4;i += 4)
3500 if (skindata[i] < 255)
3502 skinframe->hasalpha = true;
3506 if (r_loadfog && skinframe->hasalpha)
3508 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3509 memcpy(fogpixels, skindata, width * height * 4);
3510 for (i = 0;i < width * height * 4;i += 4)
3511 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3512 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3513 Mem_Free(fogpixels);
3517 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3518 //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]);
3523 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3527 skinframe_t *skinframe;
3529 if (cls.state == ca_dedicated)
3532 // if already loaded just return it, otherwise make a new skinframe
3533 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3534 if (skinframe->base)
3536 //textureflags &= ~TEXF_FORCE_RELOAD;
3538 skinframe->stain = NULL;
3539 skinframe->merged = NULL;
3540 skinframe->base = NULL;
3541 skinframe->pants = NULL;
3542 skinframe->shirt = NULL;
3543 skinframe->nmap = NULL;
3544 skinframe->gloss = NULL;
3545 skinframe->glow = NULL;
3546 skinframe->fog = NULL;
3547 skinframe->reflect = NULL;
3548 skinframe->hasalpha = false;
3550 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3554 if (developer_loading.integer)
3555 Con_Printf("loading quake skin \"%s\"\n", name);
3557 // 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)
3558 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3559 memcpy(skinframe->qpixels, skindata, width*height);
3560 skinframe->qwidth = width;
3561 skinframe->qheight = height;
3564 for (i = 0;i < width * height;i++)
3565 featuresmask |= palette_featureflags[skindata[i]];
3567 skinframe->hasalpha = false;
3570 skinframe->hasalpha = true;
3571 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3572 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3573 skinframe->qgeneratemerged = true;
3574 skinframe->qgeneratebase = skinframe->qhascolormapping;
3575 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3577 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3578 //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]);
3583 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3587 unsigned char *skindata;
3590 if (!skinframe->qpixels)
3593 if (!skinframe->qhascolormapping)
3594 colormapped = false;
3598 if (!skinframe->qgeneratebase)
3603 if (!skinframe->qgeneratemerged)
3607 width = skinframe->qwidth;
3608 height = skinframe->qheight;
3609 skindata = skinframe->qpixels;
3611 if (skinframe->qgeneratenmap)
3613 unsigned char *a, *b;
3614 skinframe->qgeneratenmap = false;
3615 a = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3616 b = a + width * height * 4;
3617 // use either a custom palette or the quake palette
3618 Image_Copy8bitBGRA(skindata, a, width * height, palette_bgra_complete);
3619 Image_HeightmapToNormalmap_BGRA(a, b, width, height, false, r_shadow_bumpscale_basetexture.value);
3620 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);
3624 if (skinframe->qgenerateglow)
3626 skinframe->qgenerateglow = false;
3627 if (skinframe->hasalpha) // fence textures
3628 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
3630 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
3635 skinframe->qgeneratebase = false;
3636 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);
3637 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);
3638 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);
3642 skinframe->qgeneratemerged = false;
3643 if (skinframe->hasalpha) // fence textures
3644 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);
3646 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);
3649 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3651 Mem_Free(skinframe->qpixels);
3652 skinframe->qpixels = NULL;
3656 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)
3659 skinframe_t *skinframe;
3662 if (cls.state == ca_dedicated)
3665 // if already loaded just return it, otherwise make a new skinframe
3666 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3667 if (skinframe->base)
3669 textureflags &= ~TEXF_FORCE_RELOAD;
3671 skinframe->stain = NULL;
3672 skinframe->merged = NULL;
3673 skinframe->base = NULL;
3674 skinframe->pants = NULL;
3675 skinframe->shirt = NULL;
3676 skinframe->nmap = NULL;
3677 skinframe->gloss = NULL;
3678 skinframe->glow = NULL;
3679 skinframe->fog = NULL;
3680 skinframe->reflect = NULL;
3681 skinframe->hasalpha = false;
3683 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3687 if (developer_loading.integer)
3688 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3690 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3691 if ((textureflags & TEXF_ALPHA) && alphapalette)
3693 for (i = 0;i < width * height;i++)
3695 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3697 skinframe->hasalpha = true;
3701 if (r_loadfog && skinframe->hasalpha)
3702 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3705 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3706 //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]);
3711 skinframe_t *R_SkinFrame_LoadMissing(void)
3713 skinframe_t *skinframe;
3715 if (cls.state == ca_dedicated)
3718 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3719 skinframe->stain = NULL;
3720 skinframe->merged = NULL;
3721 skinframe->base = NULL;
3722 skinframe->pants = NULL;
3723 skinframe->shirt = NULL;
3724 skinframe->nmap = NULL;
3725 skinframe->gloss = NULL;
3726 skinframe->glow = NULL;
3727 skinframe->fog = NULL;
3728 skinframe->reflect = NULL;
3729 skinframe->hasalpha = false;
3731 skinframe->avgcolor[0] = rand() / RAND_MAX;
3732 skinframe->avgcolor[1] = rand() / RAND_MAX;
3733 skinframe->avgcolor[2] = rand() / RAND_MAX;
3734 skinframe->avgcolor[3] = 1;
3739 skinframe_t *R_SkinFrame_LoadNoTexture(void)
3742 static unsigned char pix[16][16][4];
3744 if (cls.state == ca_dedicated)
3747 // this makes a light grey/dark grey checkerboard texture
3750 for (y = 0; y < 16; y++)
3752 for (x = 0; x < 16; x++)
3754 if ((y < 8) ^ (x < 8))
3772 return R_SkinFrame_LoadInternalBGRA("notexture", TEXF_FORCENEAREST, pix[0][0], 16, 16, false);
3775 skinframe_t *R_SkinFrame_LoadInternalUsingTexture(const char *name, int textureflags, rtexture_t *tex, int width, int height, qboolean sRGB)
3777 skinframe_t *skinframe;
3778 if (cls.state == ca_dedicated)
3780 // if already loaded just return it, otherwise make a new skinframe
3781 skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : 0, true);
3782 if (skinframe->base)
3784 textureflags &= ~TEXF_FORCE_RELOAD;
3785 skinframe->stain = NULL;
3786 skinframe->merged = NULL;
3787 skinframe->base = NULL;
3788 skinframe->pants = NULL;
3789 skinframe->shirt = NULL;
3790 skinframe->nmap = NULL;
3791 skinframe->gloss = NULL;
3792 skinframe->glow = NULL;
3793 skinframe->fog = NULL;
3794 skinframe->reflect = NULL;
3795 skinframe->hasalpha = (textureflags & TEXF_ALPHA) != 0;
3796 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3799 if (developer_loading.integer)
3800 Con_Printf("loading 32bit skin \"%s\"\n", name);
3801 skinframe->base = skinframe->merged = tex;
3802 Vector4Set(skinframe->avgcolor, 1, 1, 1, 1); // bogus placeholder
3806 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3807 typedef struct suffixinfo_s
3810 qboolean flipx, flipy, flipdiagonal;
3813 static suffixinfo_t suffix[3][6] =
3816 {"px", false, false, false},
3817 {"nx", false, false, false},
3818 {"py", false, false, false},
3819 {"ny", false, false, false},
3820 {"pz", false, false, false},
3821 {"nz", false, false, false}
3824 {"posx", false, false, false},
3825 {"negx", false, false, false},
3826 {"posy", false, false, false},
3827 {"negy", false, false, false},
3828 {"posz", false, false, false},
3829 {"negz", false, false, false}
3832 {"rt", true, false, true},
3833 {"lf", false, true, true},
3834 {"ft", true, true, false},
3835 {"bk", false, false, false},
3836 {"up", true, false, true},
3837 {"dn", true, false, true}
3841 static int componentorder[4] = {0, 1, 2, 3};
3843 static rtexture_t *R_LoadCubemap(const char *basename)
3845 int i, j, cubemapsize;
3846 unsigned char *cubemappixels, *image_buffer;
3847 rtexture_t *cubemaptexture;
3849 // must start 0 so the first loadimagepixels has no requested width/height
3851 cubemappixels = NULL;
3852 cubemaptexture = NULL;
3853 // keep trying different suffix groups (posx, px, rt) until one loads
3854 for (j = 0;j < 3 && !cubemappixels;j++)
3856 // load the 6 images in the suffix group
3857 for (i = 0;i < 6;i++)
3859 // generate an image name based on the base and and suffix
3860 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3862 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3864 // an image loaded, make sure width and height are equal
3865 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3867 // if this is the first image to load successfully, allocate the cubemap memory
3868 if (!cubemappixels && image_width >= 1)
3870 cubemapsize = image_width;
3871 // note this clears to black, so unavailable sides are black
3872 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3874 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3876 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);
3879 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3881 Mem_Free(image_buffer);
3885 // if a cubemap loaded, upload it
3888 if (developer_loading.integer)
3889 Con_Printf("loading cubemap \"%s\"\n", basename);
3891 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);
3892 Mem_Free(cubemappixels);
3896 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3897 if (developer_loading.integer)
3899 Con_Printf("(tried tried images ");
3900 for (j = 0;j < 3;j++)
3901 for (i = 0;i < 6;i++)
3902 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3903 Con_Print(" and was unable to find any of them).\n");
3906 return cubemaptexture;
3909 rtexture_t *R_GetCubemap(const char *basename)
3912 for (i = 0;i < r_texture_numcubemaps;i++)
3913 if (r_texture_cubemaps[i] != NULL)
3914 if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3915 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3916 if (i >= MAX_CUBEMAPS || !r_main_mempool)
3917 return r_texture_whitecube;
3918 r_texture_numcubemaps++;
3919 r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3920 strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3921 r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3922 return r_texture_cubemaps[i]->texture;
3925 static void R_Main_FreeViewCache(void)
3927 if (r_refdef.viewcache.entityvisible)
3928 Mem_Free(r_refdef.viewcache.entityvisible);
3929 if (r_refdef.viewcache.world_pvsbits)
3930 Mem_Free(r_refdef.viewcache.world_pvsbits);
3931 if (r_refdef.viewcache.world_leafvisible)
3932 Mem_Free(r_refdef.viewcache.world_leafvisible);
3933 if (r_refdef.viewcache.world_surfacevisible)
3934 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3935 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3938 static void R_Main_ResizeViewCache(void)
3940 int numentities = r_refdef.scene.numentities;
3941 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3942 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3943 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3944 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3945 if (r_refdef.viewcache.maxentities < numentities)
3947 r_refdef.viewcache.maxentities = numentities;
3948 if (r_refdef.viewcache.entityvisible)
3949 Mem_Free(r_refdef.viewcache.entityvisible);
3950 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3952 if (r_refdef.viewcache.world_numclusters != numclusters)
3954 r_refdef.viewcache.world_numclusters = numclusters;
3955 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3956 if (r_refdef.viewcache.world_pvsbits)
3957 Mem_Free(r_refdef.viewcache.world_pvsbits);
3958 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3960 if (r_refdef.viewcache.world_numleafs != numleafs)
3962 r_refdef.viewcache.world_numleafs = numleafs;
3963 if (r_refdef.viewcache.world_leafvisible)
3964 Mem_Free(r_refdef.viewcache.world_leafvisible);
3965 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3967 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3969 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3970 if (r_refdef.viewcache.world_surfacevisible)
3971 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3972 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3976 extern rtexture_t *loadingscreentexture;
3977 static void gl_main_start(void)
3979 loadingscreentexture = NULL;
3980 r_texture_blanknormalmap = NULL;
3981 r_texture_white = NULL;
3982 r_texture_grey128 = NULL;
3983 r_texture_black = NULL;
3984 r_texture_whitecube = NULL;
3985 r_texture_normalizationcube = NULL;
3986 r_texture_fogattenuation = NULL;
3987 r_texture_fogheighttexture = NULL;
3988 r_texture_gammaramps = NULL;
3989 r_texture_numcubemaps = 0;
3990 r_uniformbufferalignment = 32;
3992 r_loaddds = r_texture_dds_load.integer != 0;
3993 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3995 switch(vid.renderpath)
3997 case RENDERPATH_GL20:
3998 case RENDERPATH_D3D9:
3999 case RENDERPATH_D3D10:
4000 case RENDERPATH_D3D11:
4001 case RENDERPATH_SOFT:
4002 case RENDERPATH_GLES2:
4003 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4004 Cvar_SetValueQuick(&gl_combine, 1);
4005 Cvar_SetValueQuick(&r_glsl, 1);
4006 r_loadnormalmap = true;
4009 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4010 if (vid.support.arb_uniform_buffer_object)
4011 qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4014 case RENDERPATH_GL13:
4015 case RENDERPATH_GLES1:
4016 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4017 Cvar_SetValueQuick(&gl_combine, 1);
4018 Cvar_SetValueQuick(&r_glsl, 0);
4019 r_loadnormalmap = false;
4020 r_loadgloss = false;
4023 case RENDERPATH_GL11:
4024 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025 Cvar_SetValueQuick(&gl_combine, 0);
4026 Cvar_SetValueQuick(&r_glsl, 0);
4027 r_loadnormalmap = false;
4028 r_loadgloss = false;
4034 R_FrameData_Reset();
4035 R_BufferData_Reset();
4039 memset(r_queries, 0, sizeof(r_queries));
4041 r_qwskincache = NULL;
4042 r_qwskincache_size = 0;
4044 // due to caching of texture_t references, the collision cache must be reset
4045 Collision_Cache_Reset(true);
4047 // set up r_skinframe loading system for textures
4048 memset(&r_skinframe, 0, sizeof(r_skinframe));
4049 r_skinframe.loadsequence = 1;
4050 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4052 r_main_texturepool = R_AllocTexturePool();
4053 R_BuildBlankTextures();
4055 if (vid.support.arb_texture_cube_map)
4058 R_BuildNormalizationCube();
4060 r_texture_fogattenuation = NULL;
4061 r_texture_fogheighttexture = NULL;
4062 r_texture_gammaramps = NULL;
4063 //r_texture_fogintensity = NULL;
4064 memset(&r_fb, 0, sizeof(r_fb));
4065 Mem_ExpandableArray_NewArray(&r_fb.rendertargets, r_main_mempool, sizeof(r_rendertarget_t), 128);
4066 r_glsl_permutation = NULL;
4067 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4068 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4070 r_hlsl_permutation = NULL;
4071 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4072 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4074 memset(&r_svbsp, 0, sizeof (r_svbsp));
4076 memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4077 r_texture_numcubemaps = 0;
4079 r_refdef.fogmasktable_density = 0;
4082 // For Steelstorm Android
4083 // FIXME CACHE the program and reload
4084 // FIXME see possible combinations for SS:BR android
4085 Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4086 R_SetupShader_SetPermutationGLSL(0, 12);
4087 R_SetupShader_SetPermutationGLSL(0, 13);
4088 R_SetupShader_SetPermutationGLSL(0, 8388621);
4089 R_SetupShader_SetPermutationGLSL(3, 0);
4090 R_SetupShader_SetPermutationGLSL(3, 2048);
4091 R_SetupShader_SetPermutationGLSL(5, 0);
4092 R_SetupShader_SetPermutationGLSL(5, 2);
4093 R_SetupShader_SetPermutationGLSL(5, 2048);
4094 R_SetupShader_SetPermutationGLSL(5, 8388608);
4095 R_SetupShader_SetPermutationGLSL(11, 1);
4096 R_SetupShader_SetPermutationGLSL(11, 2049);
4097 R_SetupShader_SetPermutationGLSL(11, 8193);
4098 R_SetupShader_SetPermutationGLSL(11, 10241);
4099 Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4103 static void gl_main_shutdown(void)
4105 R_RenderTarget_FreeUnused(true);
4106 Mem_ExpandableArray_FreeArray(&r_fb.rendertargets);
4108 R_FrameData_Reset();
4109 R_BufferData_Reset();
4111 R_Main_FreeViewCache();
4113 switch(vid.renderpath)
4115 case RENDERPATH_GL11:
4116 case RENDERPATH_GL13:
4117 case RENDERPATH_GL20:
4118 case RENDERPATH_GLES1:
4119 case RENDERPATH_GLES2:
4120 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4122 qglDeleteQueriesARB(r_maxqueries, r_queries);
4125 case RENDERPATH_D3D9:
4126 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4128 case RENDERPATH_D3D10:
4129 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4131 case RENDERPATH_D3D11:
4132 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4134 case RENDERPATH_SOFT:
4140 memset(r_queries, 0, sizeof(r_queries));
4142 r_qwskincache = NULL;
4143 r_qwskincache_size = 0;
4145 // clear out the r_skinframe state
4146 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4147 memset(&r_skinframe, 0, sizeof(r_skinframe));
4150 Mem_Free(r_svbsp.nodes);
4151 memset(&r_svbsp, 0, sizeof (r_svbsp));
4152 R_FreeTexturePool(&r_main_texturepool);
4153 loadingscreentexture = NULL;
4154 r_texture_blanknormalmap = NULL;
4155 r_texture_white = NULL;
4156 r_texture_grey128 = NULL;
4157 r_texture_black = NULL;
4158 r_texture_whitecube = NULL;
4159 r_texture_normalizationcube = NULL;
4160 r_texture_fogattenuation = NULL;
4161 r_texture_fogheighttexture = NULL;
4162 r_texture_gammaramps = NULL;
4163 r_texture_numcubemaps = 0;
4164 //r_texture_fogintensity = NULL;
4165 memset(&r_fb, 0, sizeof(r_fb));
4168 r_glsl_permutation = NULL;
4169 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4170 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4172 r_hlsl_permutation = NULL;
4173 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4174 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4178 static void gl_main_newmap(void)
4180 // FIXME: move this code to client
4181 char *entities, entname[MAX_QPATH];
4183 Mem_Free(r_qwskincache);
4184 r_qwskincache = NULL;
4185 r_qwskincache_size = 0;
4188 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4189 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4191 CL_ParseEntityLump(entities);
4195 if (cl.worldmodel->brush.entities)
4196 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4198 R_Main_FreeViewCache();
4200 R_FrameData_Reset();
4201 R_BufferData_Reset();
4204 void GL_Main_Init(void)
4207 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4208 R_InitShaderModeInfo();
4210 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4211 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4212 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4213 if (gamemode == GAME_NEHAHRA)
4215 Cvar_RegisterVariable (&gl_fogenable);
4216 Cvar_RegisterVariable (&gl_fogdensity);
4217 Cvar_RegisterVariable (&gl_fogred);
4218 Cvar_RegisterVariable (&gl_foggreen);
4219 Cvar_RegisterVariable (&gl_fogblue);
4220 Cvar_RegisterVariable (&gl_fogstart);
4221 Cvar_RegisterVariable (&gl_fogend);
4222 Cvar_RegisterVariable (&gl_skyclip);
4224 Cvar_RegisterVariable(&r_motionblur);
4225 Cvar_RegisterVariable(&r_damageblur);
4226 Cvar_RegisterVariable(&r_motionblur_averaging);
4227 Cvar_RegisterVariable(&r_motionblur_randomize);
4228 Cvar_RegisterVariable(&r_motionblur_minblur);
4229 Cvar_RegisterVariable(&r_motionblur_maxblur);
4230 Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4231 Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4232 Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4233 Cvar_RegisterVariable(&r_motionblur_mousefactor);
4234 Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4235 Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4236 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4237 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4238 Cvar_RegisterVariable(&r_equalize_entities_by);
4239 Cvar_RegisterVariable(&r_equalize_entities_to);
4240 Cvar_RegisterVariable(&r_depthfirst);
4241 Cvar_RegisterVariable(&r_useinfinitefarclip);
4242 Cvar_RegisterVariable(&r_farclip_base);
4243 Cvar_RegisterVariable(&r_farclip_world);
4244 Cvar_RegisterVariable(&r_nearclip);
4245 Cvar_RegisterVariable(&r_deformvertexes);
4246 Cvar_RegisterVariable(&r_transparent);
4247 Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4248 Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4249 Cvar_RegisterVariable(&r_transparent_useplanardistance);
4250 Cvar_RegisterVariable(&r_showoverdraw);
4251 Cvar_RegisterVariable(&r_showbboxes);
4252 Cvar_RegisterVariable(&r_showbboxes_client);
4253 Cvar_RegisterVariable(&r_showsurfaces);
4254 Cvar_RegisterVariable(&r_showtris);
4255 Cvar_RegisterVariable(&r_shownormals);
4256 Cvar_RegisterVariable(&r_showlighting);
4257 Cvar_RegisterVariable(&r_showshadowvolumes);
4258 Cvar_RegisterVariable(&r_showcollisionbrushes);
4259 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4260 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4261 Cvar_RegisterVariable(&r_showdisabledepthtest);
4262 Cvar_RegisterVariable(&r_drawportals);
4263 Cvar_RegisterVariable(&r_drawentities);
4264 Cvar_RegisterVariable(&r_draw2d);
4265 Cvar_RegisterVariable(&r_drawworld);
4266 Cvar_RegisterVariable(&r_cullentities_trace);
4267 Cvar_RegisterVariable(&r_cullentities_trace_entityocclusion);
4268 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4269 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4270 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4271 Cvar_RegisterVariable(&r_cullentities_trace_expand);
4272 Cvar_RegisterVariable(&r_cullentities_trace_pad);
4273 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4274 Cvar_RegisterVariable(&r_cullentities_trace_eyejitter);
4275 Cvar_RegisterVariable(&r_sortentities);
4276 Cvar_RegisterVariable(&r_drawviewmodel);
4277 Cvar_RegisterVariable(&r_drawexteriormodel);
4278 Cvar_RegisterVariable(&r_speeds);
4279 Cvar_RegisterVariable(&r_fullbrights);
4280 Cvar_RegisterVariable(&r_wateralpha);
4281 Cvar_RegisterVariable(&r_dynamic);
4282 Cvar_RegisterVariable(&r_fakelight);
4283 Cvar_RegisterVariable(&r_fakelight_intensity);
4284 Cvar_RegisterVariable(&r_fullbright_directed);
4285 Cvar_RegisterVariable(&r_fullbright_directed_ambient);
4286 Cvar_RegisterVariable(&r_fullbright_directed_diffuse);
4287 Cvar_RegisterVariable(&r_fullbright_directed_pitch);
4288 Cvar_RegisterVariable(&r_fullbright_directed_pitch_relative);
4289 Cvar_RegisterVariable(&r_fullbright);
4290 Cvar_RegisterVariable(&r_shadows);
4291 Cvar_RegisterVariable(&r_shadows_darken);
4292 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4293 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4294 Cvar_RegisterVariable(&r_shadows_throwdistance);
4295 Cvar_RegisterVariable(&r_shadows_throwdirection);
4296 Cvar_RegisterVariable(&r_shadows_focus);
4297 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4298 Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4299 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4300 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4301 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4302 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4303 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4304 Cvar_RegisterVariable(&r_fog_exp2);
4305 Cvar_RegisterVariable(&r_fog_clear);
4306 Cvar_RegisterVariable(&r_drawfog);
4307 Cvar_RegisterVariable(&r_transparentdepthmasking);
4308 Cvar_RegisterVariable(&r_transparent_sortmindist);
4309 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4310 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4311 Cvar_RegisterVariable(&r_texture_dds_load);
4312 Cvar_RegisterVariable(&r_texture_dds_save);
4313 Cvar_RegisterVariable(&r_textureunits);
4314 Cvar_RegisterVariable(&gl_combine);
4315 Cvar_RegisterVariable(&r_usedepthtextures);
4316 Cvar_RegisterVariable(&r_viewfbo);
4317 Cvar_RegisterVariable(&r_rendertarget_debug);
4318 Cvar_RegisterVariable(&r_viewscale);
4319 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4320 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4321 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4322 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4323 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4324 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4325 Cvar_RegisterVariable(&r_glsl);
4326 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4327 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4328 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4329 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4330 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4331 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4332 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4333 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4334 Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4335 Cvar_RegisterVariable(&r_glsl_postprocess);
4336 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4337 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4338 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4339 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4340 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4341 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4342 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4343 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4344 Cvar_RegisterVariable(&r_celshading);
4345 Cvar_RegisterVariable(&r_celoutlines);
4347 Cvar_RegisterVariable(&r_water);
4348 Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4349 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4350 Cvar_RegisterVariable(&r_water_clippingplanebias);
4351 Cvar_RegisterVariable(&r_water_refractdistort);
4352 Cvar_RegisterVariable(&r_water_reflectdistort);
4353 Cvar_RegisterVariable(&r_water_scissormode);
4354 Cvar_RegisterVariable(&r_water_lowquality);
4355 Cvar_RegisterVariable(&r_water_hideplayer);
4357 Cvar_RegisterVariable(&r_lerpsprites);
4358 Cvar_RegisterVariable(&r_lerpmodels);
4359 Cvar_RegisterVariable(&r_lerplightstyles);
4360 Cvar_RegisterVariable(&r_waterscroll);
4361 Cvar_RegisterVariable(&r_bloom);
4362 Cvar_RegisterVariable(&r_bloom_colorscale);
4363 Cvar_RegisterVariable(&r_bloom_brighten);
4364 Cvar_RegisterVariable(&r_bloom_blur);
4365 Cvar_RegisterVariable(&r_bloom_resolution);
4366 Cvar_RegisterVariable(&r_bloom_colorexponent);
4367 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4368 Cvar_RegisterVariable(&r_bloom_scenebrightness);
4369 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4370 Cvar_RegisterVariable(&r_hdr_glowintensity);
4371 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4372 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4373 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4374 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4375 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4376 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4377 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4378 Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4379 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4380 Cvar_RegisterVariable(&developer_texturelogging);
4381 Cvar_RegisterVariable(&gl_lightmaps);
4382 Cvar_RegisterVariable(&r_test);
4383 Cvar_RegisterVariable(&r_batch_multidraw);
4384 Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4385 Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4386 Cvar_RegisterVariable(&r_glsl_skeletal);
4387 Cvar_RegisterVariable(&r_glsl_saturation);
4388 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4389 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4390 Cvar_RegisterVariable(&r_framedatasize);
4391 for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4392 Cvar_RegisterVariable(&r_buffermegs[i]);
4393 Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4394 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4395 Cvar_SetValue("r_fullbrights", 0);
4396 #ifdef DP_MOBILETOUCH
4397 // GLES devices have terrible depth precision in general, so...
4398 Cvar_SetValueQuick(&r_nearclip, 4);
4399 Cvar_SetValueQuick(&r_farclip_base, 4096);
4400 Cvar_SetValueQuick(&r_farclip_world, 0);
4401 Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4403 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4406 void Render_Init(void)
4419 R_LightningBeams_Init();
4429 extern char *ENGINE_EXTENSIONS;
4432 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4433 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4434 gl_version = (const char *)qglGetString(GL_VERSION);
4435 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4439 if (!gl_platformextensions)
4440 gl_platformextensions = "";
4442 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4443 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4444 Con_Printf("GL_VERSION: %s\n", gl_version);
4445 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4446 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4448 VID_CheckExtensions();
4450 // LordHavoc: report supported extensions
4452 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4454 Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4457 // clear to black (loading plaque will be seen over this)
4458 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4462 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4466 if (r_trippy.integer)
4468 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4470 p = r_refdef.view.frustum + i;
4475 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4479 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4483 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4487 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4491 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4495 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4499 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4503 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4511 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4515 if (r_trippy.integer)
4517 for (i = 0;i < numplanes;i++)
4524 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4528 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4532 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4536 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4540 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4544 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4548 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4552 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4560 //==================================================================================
4562 // LordHavoc: this stores temporary data used within the same frame
4564 typedef struct r_framedata_mem_s
4566 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4567 size_t size; // how much usable space
4568 size_t current; // how much space in use
4569 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4570 size_t wantedsize; // how much space was allocated
4571 unsigned char *data; // start of real data (16byte aligned)
4575 static r_framedata_mem_t *r_framedata_mem;
4577 void R_FrameData_Reset(void)
4579 while (r_framedata_mem)
4581 r_framedata_mem_t *next = r_framedata_mem->purge;
4582 Mem_Free(r_framedata_mem);
4583 r_framedata_mem = next;
4587 static void R_FrameData_Resize(qboolean mustgrow)
4590 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4591 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4592 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4594 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4595 newmem->wantedsize = wantedsize;
4596 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4597 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4598 newmem->current = 0;
4600 newmem->purge = r_framedata_mem;
4601 r_framedata_mem = newmem;
4605 void R_FrameData_NewFrame(void)
4607 R_FrameData_Resize(false);
4608 if (!r_framedata_mem)
4610 // if we ran out of space on the last frame, free the old memory now
4611 while (r_framedata_mem->purge)
4613 // repeatedly remove the second item in the list, leaving only head
4614 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4615 Mem_Free(r_framedata_mem->purge);
4616 r_framedata_mem->purge = next;
4618 // reset the current mem pointer
4619 r_framedata_mem->current = 0;
4620 r_framedata_mem->mark = 0;
4623 void *R_FrameData_Alloc(size_t size)
4628 // align to 16 byte boundary - the data pointer is already aligned, so we
4629 // only need to ensure the size of every allocation is also aligned
4630 size = (size + 15) & ~15;
4632 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4634 // emergency - we ran out of space, allocate more memory
4635 // note: this has no upper-bound, we'll fail to allocate memory eventually and just die
4636 newvalue = r_framedatasize.value * 2.0f;
4637 // 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
4638 if (sizeof(size_t) >= 8)
4639 newvalue = bound(0.25f, newvalue, (float)(1ll << 42));
4641 newvalue = bound(0.25f, newvalue, (float)(1 << 10));
4642 // this might not be a growing it, but we'll allocate another buffer every time
4643 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4644 R_FrameData_Resize(true);
4647 data = r_framedata_mem->data + r_framedata_mem->current;
4648 r_framedata_mem->current += size;
4650 // count the usage for stats
4651 r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4652 r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4654 return (void *)data;
4657 void *R_FrameData_Store(size_t size, void *data)
4659 void *d = R_FrameData_Alloc(size);
4661 memcpy(d, data, size);
4665 void R_FrameData_SetMark(void)
4667 if (!r_framedata_mem)
4669 r_framedata_mem->mark = r_framedata_mem->current;
4672 void R_FrameData_ReturnToMark(void)
4674 if (!r_framedata_mem)
4676 r_framedata_mem->current = r_framedata_mem->mark;
4679 //==================================================================================
4681 // avoid reusing the same buffer objects on consecutive frames
4682 #define R_BUFFERDATA_CYCLE 3
4684 typedef struct r_bufferdata_buffer_s
4686 struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4687 size_t size; // how much usable space
4688 size_t current; // how much space in use
4689 r_meshbuffer_t *buffer; // the buffer itself
4691 r_bufferdata_buffer_t;
4693 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4694 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4696 /// frees all dynamic buffers
4697 void R_BufferData_Reset(void)
4700 r_bufferdata_buffer_t **p, *mem;
4701 for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4703 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4706 p = &r_bufferdata_buffer[cycle][type];
4712 R_Mesh_DestroyMeshBuffer(mem->buffer);
4719 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4720 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4722 r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4724 float newvalue = r_buffermegs[type].value;
4726 // increase the cvar if we have to (but only if we already have a mem)
4727 if (mustgrow && mem)
4729 newvalue = bound(0.25f, newvalue, 256.0f);
4730 while (newvalue * 1024*1024 < minsize)
4733 // clamp the cvar to valid range
4734 newvalue = bound(0.25f, newvalue, 256.0f);
4735 if (r_buffermegs[type].value != newvalue)
4736 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4738 // calculate size in bytes
4739 size = (size_t)(newvalue * 1024*1024);
4740 size = bound(131072, size, 256*1024*1024);
4742 // allocate a new buffer if the size is different (purge old one later)
4743 // or if we were told we must grow the buffer
4744 if (!mem || mem->size != size || mustgrow)
4746 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4749 if (type == R_BUFFERDATA_VERTEX)
4750 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4751 else if (type == R_BUFFERDATA_INDEX16)
4752 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4753 else if (type == R_BUFFERDATA_INDEX32)
4754 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4755 else if (type == R_BUFFERDATA_UNIFORM)
4756 mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4757 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4758 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4762 void R_BufferData_NewFrame(void)
4765 r_bufferdata_buffer_t **p, *mem;
4766 // cycle to the next frame's buffers
4767 r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4768 // if we ran out of space on the last time we used these buffers, free the old memory now
4769 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4771 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4773 R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4774 // free all but the head buffer, this is how we recycle obsolete
4775 // buffers after they are no longer in use
4776 p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4782 R_Mesh_DestroyMeshBuffer(mem->buffer);
4785 // reset the current offset
4786 r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4791 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4793 r_bufferdata_buffer_t *mem;
4797 *returnbufferoffset = 0;
4799 // align size to a byte boundary appropriate for the buffer type, this
4800 // makes all allocations have aligned start offsets
4801 if (type == R_BUFFERDATA_UNIFORM)
4802 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4804 padsize = (datasize + 15) & ~15;
4806 // if we ran out of space in this buffer we must allocate a new one
4807 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)
4808 R_BufferData_Resize(type, true, padsize);
4810 // if the resize did not give us enough memory, fail
4811 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)
4812 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4814 mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4815 offset = (int)mem->current;
4816 mem->current += padsize;
4818 // upload the data to the buffer at the chosen offset
4820 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4821 R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4823 // count the usage for stats
4824 r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4825 r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4827 // return the buffer offset
4828 *returnbufferoffset = offset;
4833 //==================================================================================
4835 // LordHavoc: animcache originally written by Echon, rewritten since then
4838 * Animation cache prevents re-generating mesh data for an animated model
4839 * multiple times in one frame for lighting, shadowing, reflections, etc.
4842 void R_AnimCache_Free(void)
4846 void R_AnimCache_ClearCache(void)
4849 entity_render_t *ent;
4851 for (i = 0;i < r_refdef.scene.numentities;i++)
4853 ent = r_refdef.scene.entities[i];
4854 ent->animcache_vertex3f = NULL;
4855 ent->animcache_vertex3f_vertexbuffer = NULL;
4856 ent->animcache_vertex3f_bufferoffset = 0;
4857 ent->animcache_normal3f = NULL;
4858 ent->animcache_normal3f_vertexbuffer = NULL;
4859 ent->animcache_normal3f_bufferoffset = 0;
4860 ent->animcache_svector3f = NULL;
4861 ent->animcache_svector3f_vertexbuffer = NULL;
4862 ent->animcache_svector3f_bufferoffset = 0;
4863 ent->animcache_tvector3f = NULL;
4864 ent->animcache_tvector3f_vertexbuffer = NULL;
4865 ent->animcache_tvector3f_bufferoffset = 0;
4866 ent->animcache_vertexmesh = NULL;
4867 ent->animcache_vertexmesh_vertexbuffer = NULL;
4868 ent->animcache_vertexmesh_bufferoffset = 0;
4869 ent->animcache_skeletaltransform3x4 = NULL;
4870 ent->animcache_skeletaltransform3x4buffer = NULL;
4871 ent->animcache_skeletaltransform3x4offset = 0;
4872 ent->animcache_skeletaltransform3x4size = 0;
4876 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4880 // check if we need the meshbuffers
4881 if (!vid.useinterleavedarrays)
4884 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4885 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4886 // TODO: upload vertexbuffer?
4887 if (ent->animcache_vertexmesh)
4889 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4890 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4891 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4892 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4893 for (i = 0;i < numvertices;i++)
4894 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4895 if (ent->animcache_svector3f)
4896 for (i = 0;i < numvertices;i++)
4897 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4898 if (ent->animcache_tvector3f)
4899 for (i = 0;i < numvertices;i++)
4900 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4901 if (ent->animcache_normal3f)
4902 for (i = 0;i < numvertices;i++)
4903 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4907 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4909 dp_model_t *model = ent->model;
4912 // see if this ent is worth caching
4913 if (!model || !model->Draw || !model->AnimateVertices)
4915 // nothing to cache if it contains no animations and has no skeleton
4916 if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4918 // see if it is already cached for gpuskeletal
4919 if (ent->animcache_skeletaltransform3x4)
4921 // see if it is already cached as a mesh
4922 if (ent->animcache_vertex3f)
4924 // check if we need to add normals or tangents
4925 if (ent->animcache_normal3f)
4926 wantnormals = false;
4927 if (ent->animcache_svector3f)
4928 wanttangents = false;
4929 if (!wantnormals && !wanttangents)
4933 // check which kind of cache we need to generate
4934 if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4936 // cache the skeleton so the vertex shader can use it
4937 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4938 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4939 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4940 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4941 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4);
4942 // note: this can fail if the buffer is at the grow limit
4943 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4944 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4946 else if (ent->animcache_vertex3f)
4948 // mesh was already cached but we may need to add normals/tangents
4949 // (this only happens with multiple views, reflections, cameras, etc)
4950 if (wantnormals || wanttangents)
4952 numvertices = model->surfmesh.num_vertices;
4954 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4957 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4958 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4960 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4961 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4962 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4963 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4964 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4969 // generate mesh cache
4970 numvertices = model->surfmesh.num_vertices;
4971 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4973 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4976 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4977 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4980 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4981 if (wantnormals || wanttangents)
4983 r_refdef.stats[r_stat_animcache_shade_count] += 1;
4984 r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4985 r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4987 r_refdef.stats[r_stat_animcache_shape_count] += 1;
4988 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
4989 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
4994 void R_AnimCache_CacheVisibleEntities(void)
4997 qboolean wantnormals = true;
4998 qboolean wanttangents = !r_showsurfaces.integer;
5000 switch(vid.renderpath)
5002 case RENDERPATH_GL20:
5003 case RENDERPATH_D3D9:
5004 case RENDERPATH_D3D10:
5005 case RENDERPATH_D3D11:
5006 case RENDERPATH_GLES2:
5008 case RENDERPATH_GL11:
5009 case RENDERPATH_GL13:
5010 case RENDERPATH_GLES1:
5011 wanttangents = false;
5013 case RENDERPATH_SOFT:
5017 if (r_shownormals.integer)
5018 wanttangents = wantnormals = true;
5020 // TODO: thread this
5021 // NOTE: R_PrepareRTLights() also caches entities
5023 for (i = 0;i < r_refdef.scene.numentities;i++)
5024 if (r_refdef.viewcache.entityvisible[i])
5025 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5028 //==================================================================================
5030 qboolean R_CanSeeBox(int numsamples, vec_t eyejitter, vec_t entboxenlarge, vec_t entboxexpand, vec_t pad, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5033 vec3_t eyemins, eyemaxs;
5034 vec3_t boxmins, boxmaxs;
5035 vec3_t padmins, padmaxs;
5038 dp_model_t *model = r_refdef.scene.worldmodel;
5039 static vec3_t positions[] = {
5040 { 0.5f, 0.5f, 0.5f },
5041 { 0.0f, 0.0f, 0.0f },
5042 { 0.0f, 0.0f, 1.0f },
5043 { 0.0f, 1.0f, 0.0f },
5044 { 0.0f, 1.0f, 1.0f },
5045 { 1.0f, 0.0f, 0.0f },
5046 { 1.0f, 0.0f, 1.0f },
5047 { 1.0f, 1.0f, 0.0f },
5048 { 1.0f, 1.0f, 1.0f },
5051 // sample count can be set to -1 to skip this logic, for flicker-prone objects
5055 // view origin is not used for culling in portal/reflection/refraction renders or isometric views
5056 if (r_refdef.view.useclipplane || !r_refdef.view.useperspective || r_trippy.integer)
5059 if (!r_cullentities_trace_entityocclusion.integer && (!model || !model->brush.TraceLineOfSight))
5062 // expand the eye box a little
5063 eyemins[0] = eye[0] - eyejitter;
5064 eyemaxs[0] = eye[0] + eyejitter;
5065 eyemins[1] = eye[1] - eyejitter;
5066 eyemaxs[1] = eye[1] + eyejitter;
5067 eyemins[2] = eye[2] - eyejitter;
5068 eyemaxs[2] = eye[2] + eyejitter;
5069 // expand the box a little
5070 boxmins[0] = (entboxenlarge + 1) * entboxmins[0] - entboxenlarge * entboxmaxs[0] - entboxexpand;
5071 boxmaxs[0] = (entboxenlarge + 1) * entboxmaxs[0] - entboxenlarge * entboxmins[0] + entboxexpand;
5072 boxmins[1] = (entboxenlarge + 1) * entboxmins[1] - entboxenlarge * entboxmaxs[1] - entboxexpand;
5073 boxmaxs[1] = (entboxenlarge + 1) * entboxmaxs[1] - entboxenlarge * entboxmins[1] + entboxexpand;
5074 boxmins[2] = (entboxenlarge + 1) * entboxmins[2] - entboxenlarge * entboxmaxs[2] - entboxexpand;
5075 boxmaxs[2] = (entboxenlarge + 1) * entboxmaxs[2] - entboxenlarge * entboxmins[2] + entboxexpand;
5076 // make an even larger box for the acceptable area
5077 padmins[0] = boxmins[0] - pad;
5078 padmaxs[0] = boxmaxs[0] + pad;
5079 padmins[1] = boxmins[1] - pad;
5080 padmaxs[1] = boxmaxs[1] + pad;
5081 padmins[2] = boxmins[2] - pad;
5082 padmaxs[2] = boxmaxs[2] + pad;
5084 // return true if eye overlaps enlarged box
5085 if (BoxesOverlap(boxmins, boxmaxs, eyemins, eyemaxs))
5088 // try specific positions in the box first - note that these can be cached
5089 if (r_cullentities_trace_entityocclusion.integer)
5091 for (i = 0; i < sizeof(positions) / sizeof(positions[0]); i++)
5093 VectorCopy(eye, start);
5094 end[0] = boxmins[0] + (boxmaxs[0] - boxmins[0]) * positions[i][0];
5095 end[1] = boxmins[1] + (boxmaxs[1] - boxmins[1]) * positions[i][1];
5096 end[2] = boxmins[2] + (boxmaxs[2] - boxmins[2]) * positions[i][2];
5097 //trace_t trace = CL_TraceLine(start, end, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID, SUPERCONTENTS_SKY, 0.0f, true, false, NULL, true, true);
5098 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5099 // not picky - if the trace ended anywhere in the box we're good
5100 if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5104 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5107 // try various random positions
5108 for (i = 0; i < numsamples; i++)
5110 VectorSet(start, lhrandom(eyemins[0], eyemaxs[0]), lhrandom(eyemins[1], eyemaxs[1]), lhrandom(eyemins[2], eyemaxs[2]));
5111 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5112 if (r_cullentities_trace_entityocclusion.integer)
5114 trace_t trace = CL_Cache_TraceLineSurfaces(start, end, MOVE_NORMAL, SUPERCONTENTS_SOLID, 0, MATERIALFLAGMASK_TRANSLUCENT);
5115 // not picky - if the trace ended anywhere in the box we're good
5116 if (BoxesOverlap(trace.endpos, trace.endpos, padmins, padmaxs))
5119 else if (model->brush.TraceLineOfSight(model, start, end, padmins, padmaxs))
5127 static void R_View_UpdateEntityVisible (void)
5132 entity_render_t *ent;
5134 if (r_refdef.envmap || r_fb.water.hideplayer)
5135 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5136 else if (chase_active.integer || r_fb.water.renderingscene)
5137 renderimask = RENDER_VIEWMODEL;
5139 renderimask = RENDER_EXTERIORMODEL;
5140 if (!r_drawviewmodel.integer)
5141 renderimask |= RENDER_VIEWMODEL;
5142 if (!r_drawexteriormodel.integer)
5143 renderimask |= RENDER_EXTERIORMODEL;
5144 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5145 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5147 // worldmodel can check visibility
5148 for (i = 0;i < r_refdef.scene.numentities;i++)
5150 ent = r_refdef.scene.entities[i];
5151 if (!(ent->flags & renderimask))
5152 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)))
5153 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))
5154 r_refdef.viewcache.entityvisible[i] = true;
5159 // no worldmodel or it can't check visibility
5160 for (i = 0;i < r_refdef.scene.numentities;i++)
5162 ent = r_refdef.scene.entities[i];
5163 if (!(ent->flags & renderimask))
5164 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)))
5165 r_refdef.viewcache.entityvisible[i] = true;
5168 if (r_cullentities_trace.integer)
5170 for (i = 0;i < r_refdef.scene.numentities;i++)
5172 if (!r_refdef.viewcache.entityvisible[i])
5174 ent = r_refdef.scene.entities[i];
5175 if (!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5177 samples = ent->last_trace_visibility == 0 ? r_cullentities_trace_tempentitysamples.integer : r_cullentities_trace_samples.integer;
5178 if (R_CanSeeBox(samples, r_cullentities_trace_eyejitter.value, r_cullentities_trace_enlarge.value, r_cullentities_trace_expand.value, r_cullentities_trace_pad.value, r_refdef.view.origin, ent->mins, ent->maxs))
5179 ent->last_trace_visibility = realtime;
5180 if (ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5181 r_refdef.viewcache.entityvisible[i] = 0;
5187 /// only used if skyrendermasked, and normally returns false
5188 static int R_DrawBrushModelsSky (void)
5191 entity_render_t *ent;
5194 for (i = 0;i < r_refdef.scene.numentities;i++)
5196 if (!r_refdef.viewcache.entityvisible[i])
5198 ent = r_refdef.scene.entities[i];
5199 if (!ent->model || !ent->model->DrawSky)
5201 ent->model->DrawSky(ent);
5207 static void R_DrawNoModel(entity_render_t *ent);
5208 static void R_DrawModels(void)
5211 entity_render_t *ent;
5213 for (i = 0;i < r_refdef.scene.numentities;i++)
5215 if (!r_refdef.viewcache.entityvisible[i])
5217 ent = r_refdef.scene.entities[i];
5218 r_refdef.stats[r_stat_entities]++;
5220 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5223 Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5224 Con_Printf("R_DrawModels\n");
5225 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]);
5226 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);
5227 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);
5230 if (ent->model && ent->model->Draw != NULL)
5231 ent->model->Draw(ent);
5237 static void R_DrawModelsDepth(void)
5240 entity_render_t *ent;
5242 for (i = 0;i < r_refdef.scene.numentities;i++)
5244 if (!r_refdef.viewcache.entityvisible[i])
5246 ent = r_refdef.scene.entities[i];
5247 if (ent->model && ent->model->DrawDepth != NULL)
5248 ent->model->DrawDepth(ent);
5252 static void R_DrawModelsDebug(void)
5255 entity_render_t *ent;
5257 for (i = 0;i < r_refdef.scene.numentities;i++)
5259 if (!r_refdef.viewcache.entityvisible[i])
5261 ent = r_refdef.scene.entities[i];
5262 if (ent->model && ent->model->DrawDebug != NULL)
5263 ent->model->DrawDebug(ent);
5267 static void R_DrawModelsAddWaterPlanes(void)
5270 entity_render_t *ent;
5272 for (i = 0;i < r_refdef.scene.numentities;i++)
5274 if (!r_refdef.viewcache.entityvisible[i])
5276 ent = r_refdef.scene.entities[i];
5277 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5278 ent->model->DrawAddWaterPlanes(ent);
5282 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}};
5284 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5286 if (r_hdr_irisadaptation.integer)
5291 vec3_t diffusenormal;
5293 vec_t brightness = 0.0f;
5298 VectorCopy(r_refdef.view.forward, forward);
5299 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5301 p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5302 p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5303 p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5304 R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT, r_refdef.scene.lightmapintensity, r_refdef.scene.ambientintensity);
5305 d = DotProduct(forward, diffusenormal);
5306 brightness += VectorLength(ambient);
5308 brightness += d * VectorLength(diffuse);
5310 brightness *= 1.0f / c;
5311 brightness += 0.00001f; // make sure it's never zero
5312 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5313 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5314 current = r_hdr_irisadaptation_value.value;
5316 current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5317 else if (current > goal)
5318 current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5319 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5320 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5322 else if (r_hdr_irisadaptation_value.value != 1.0f)
5323 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5326 static void R_View_SetFrustum(const int *scissor)
5329 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5330 vec3_t forward, left, up, origin, v;
5334 // flipped x coordinates (because x points left here)
5335 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5336 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5338 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5339 switch(vid.renderpath)
5341 case RENDERPATH_D3D9:
5342 case RENDERPATH_D3D10:
5343 case RENDERPATH_D3D11:
5344 // non-flipped y coordinates
5345 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5346 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5348 case RENDERPATH_SOFT:
5349 case RENDERPATH_GL11:
5350 case RENDERPATH_GL13:
5351 case RENDERPATH_GL20:
5352 case RENDERPATH_GLES1:
5353 case RENDERPATH_GLES2:
5354 // non-flipped y coordinates
5355 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5356 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5361 // we can't trust r_refdef.view.forward and friends in reflected scenes
5362 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5365 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5366 r_refdef.view.frustum[0].normal[1] = 0 - 0;
5367 r_refdef.view.frustum[0].normal[2] = -1 - 0;
5368 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5369 r_refdef.view.frustum[1].normal[1] = 0 + 0;
5370 r_refdef.view.frustum[1].normal[2] = -1 + 0;
5371 r_refdef.view.frustum[2].normal[0] = 0 - 0;
5372 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5373 r_refdef.view.frustum[2].normal[2] = -1 - 0;
5374 r_refdef.view.frustum[3].normal[0] = 0 + 0;
5375 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5376 r_refdef.view.frustum[3].normal[2] = -1 + 0;
5380 zNear = r_refdef.nearclip;
5381 nudge = 1.0 - 1.0 / (1<<23);
5382 r_refdef.view.frustum[4].normal[0] = 0 - 0;
5383 r_refdef.view.frustum[4].normal[1] = 0 - 0;
5384 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5385 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5386 r_refdef.view.frustum[5].normal[0] = 0 + 0;
5387 r_refdef.view.frustum[5].normal[1] = 0 + 0;
5388 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5389 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5395 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5396 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5397 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5398 r_refdef.view.frustum[0].dist = m[15] - m[12];
5400 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5401 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5402 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5403 r_refdef.view.frustum[1].dist = m[15] + m[12];
5405 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5406 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5407 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5408 r_refdef.view.frustum[2].dist = m[15] - m[13];
5410 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5411 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5412 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5413 r_refdef.view.frustum[3].dist = m[15] + m[13];
5415 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5416 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5417 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5418 r_refdef.view.frustum[4].dist = m[15] - m[14];
5420 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5421 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5422 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5423 r_refdef.view.frustum[5].dist = m[15] + m[14];
5426 if (r_refdef.view.useperspective)
5428 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5429 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]);
5430 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]);
5431 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]);
5432 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]);
5434 // then the normals from the corners relative to origin
5435 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5436 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5437 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5438 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5440 // in a NORMAL view, forward cross left == up
5441 // in a REFLECTED view, forward cross left == down
5442 // so our cross products above need to be adjusted for a left handed coordinate system
5443 CrossProduct(forward, left, v);
5444 if(DotProduct(v, up) < 0)
5446 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5447 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5448 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5449 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5452 // Leaving those out was a mistake, those were in the old code, and they
5453 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5454 // I couldn't reproduce it after adding those normalizations. --blub
5455 VectorNormalize(r_refdef.view.frustum[0].normal);
5456 VectorNormalize(r_refdef.view.frustum[1].normal);
5457 VectorNormalize(r_refdef.view.frustum[2].normal);
5458 VectorNormalize(r_refdef.view.frustum[3].normal);
5460 // make the corners absolute
5461 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5462 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5463 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5464 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5467 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5469 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5470 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5471 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5472 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5473 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5477 VectorScale(forward, -1.0f, r_refdef.view.frustum[0].normal);
5478 VectorScale(forward, 1.0f, r_refdef.view.frustum[1].normal);
5479 VectorScale(left, -1.0f, r_refdef.view.frustum[2].normal);
5480 VectorScale(left, 1.0f, r_refdef.view.frustum[3].normal);
5481 VectorScale(up, -1.0f, r_refdef.view.frustum[4].normal);
5482 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) - r_refdef.view.ortho_x;
5483 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) - r_refdef.view.ortho_x;
5484 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) - r_refdef.view.ortho_y;
5485 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) - r_refdef.view.ortho_y;
5486 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5488 r_refdef.view.numfrustumplanes = 5;
5490 if (r_refdef.view.useclipplane)
5492 r_refdef.view.numfrustumplanes = 6;
5493 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5496 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5497 PlaneClassify(r_refdef.view.frustum + i);
5499 // LordHavoc: note to all quake engine coders, Quake had a special case
5500 // for 90 degrees which assumed a square view (wrong), so I removed it,
5501 // Quake2 has it disabled as well.
5503 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5504 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5505 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5506 //PlaneClassify(&frustum[0]);
5508 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5509 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5510 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5511 //PlaneClassify(&frustum[1]);
5513 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5514 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5515 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5516 //PlaneClassify(&frustum[2]);
5518 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5519 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5520 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5521 //PlaneClassify(&frustum[3]);
5524 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5525 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5526 //PlaneClassify(&frustum[4]);
5529 static void R_View_UpdateWithScissor(const int *myscissor)
5531 R_Main_ResizeViewCache();
5532 R_View_SetFrustum(myscissor);
5533 R_View_WorldVisibility(r_refdef.view.useclipplane);
5534 R_View_UpdateEntityVisible();
5537 static void R_View_Update(void)
5539 R_Main_ResizeViewCache();
5540 R_View_SetFrustum(NULL);
5541 R_View_WorldVisibility(r_refdef.view.useclipplane);
5542 R_View_UpdateEntityVisible();
5545 float viewscalefpsadjusted = 1.0f;
5547 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5549 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5550 scale = bound(0.03125f, scale, 1.0f);
5551 *outwidth = (int)ceil(width * scale);
5552 *outheight = (int)ceil(height * scale);
5555 void R_SetupView(qboolean allowwaterclippingplane, int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5557 const float *customclipplane = NULL;
5559 int /*rtwidth,*/ rtheight;
5560 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5562 // LadyHavoc: couldn't figure out how to make this approach work the same in DPSOFTRAST
5563 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5564 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5565 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5566 dist = r_refdef.view.clipplane.dist;
5567 plane[0] = r_refdef.view.clipplane.normal[0];
5568 plane[1] = r_refdef.view.clipplane.normal[1];
5569 plane[2] = r_refdef.view.clipplane.normal[2];
5571 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5574 //rtwidth = viewfbo ? R_TextureWidth(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.width;
5575 rtheight = viewfbo ? R_TextureHeight(viewdepthtexture ? viewdepthtexture : viewcolortexture) : vid.height;
5577 if (!r_refdef.view.useperspective)
5578 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, -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);
5579 else if (vid.stencil && r_useinfinitefarclip.integer)
5580 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5582 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, viewx, rtheight - viewheight - viewy, viewwidth, viewheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5583 R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5584 R_SetViewport(&r_refdef.view.viewport);
5585 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5587 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5588 float screenplane[4];
5589 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5590 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5591 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5592 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5593 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5597 void R_EntityMatrix(const matrix4x4_t *matrix)
5599 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5601 gl_modelmatrixchanged = false;
5602 gl_modelmatrix = *matrix;
5603 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5604 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5605 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5606 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5608 switch(vid.renderpath)
5610 case RENDERPATH_D3D9:
5612 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5613 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5616 case RENDERPATH_D3D10:
5617 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5619 case RENDERPATH_D3D11:
5620 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5622 case RENDERPATH_GL11:
5623 case RENDERPATH_GL13:
5624 case RENDERPATH_GLES1:
5626 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5629 case RENDERPATH_SOFT:
5630 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5631 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5633 case RENDERPATH_GL20:
5634 case RENDERPATH_GLES2:
5635 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5636 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5642 void R_ResetViewRendering2D_Common(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight, float x2, float y2)
5644 r_viewport_t viewport;
5648 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5649 R_Viewport_InitOrtho(&viewport, &identitymatrix, viewx, vid.height - viewheight - viewy, viewwidth, viewheight, 0, 0, x2, y2, -10, 100, NULL);
5650 R_Mesh_SetRenderTargets(viewfbo, viewdepthtexture, viewcolortexture, NULL, NULL, NULL);
5651 R_SetViewport(&viewport);
5652 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5653 GL_Color(1, 1, 1, 1);
5654 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5655 GL_BlendFunc(GL_ONE, GL_ZERO);
5656 GL_ScissorTest(false);
5657 GL_DepthMask(false);
5658 GL_DepthRange(0, 1);
5659 GL_DepthTest(false);
5660 GL_DepthFunc(GL_LEQUAL);
5661 R_EntityMatrix(&identitymatrix);
5662 R_Mesh_ResetTextureState();
5663 GL_PolygonOffset(0, 0);
5664 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5665 switch(vid.renderpath)
5667 case RENDERPATH_GL11:
5668 case RENDERPATH_GL13:
5669 case RENDERPATH_GL20:
5670 case RENDERPATH_GLES1:
5671 case RENDERPATH_GLES2:
5672 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5674 case RENDERPATH_D3D9:
5675 case RENDERPATH_D3D10:
5676 case RENDERPATH_D3D11:
5677 case RENDERPATH_SOFT:
5680 GL_CullFace(GL_NONE);
5685 void R_ResetViewRendering2D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5689 R_ResetViewRendering2D_Common(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight, 1.0f, 1.0f);
5692 void R_ResetViewRendering3D(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
5696 R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
5697 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5698 GL_Color(1, 1, 1, 1);
5699 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5700 GL_BlendFunc(GL_ONE, GL_ZERO);
5701 GL_ScissorTest(true);
5703 GL_DepthRange(0, 1);
5705 GL_DepthFunc(GL_LEQUAL);
5706 R_EntityMatrix(&identitymatrix);
5707 R_Mesh_ResetTextureState();
5708 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5709 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5710 switch(vid.renderpath)
5712 case RENDERPATH_GL11:
5713 case RENDERPATH_GL13:
5714 case RENDERPATH_GL20:
5715 case RENDERPATH_GLES1:
5716 case RENDERPATH_GLES2:
5717 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5719 case RENDERPATH_D3D9:
5720 case RENDERPATH_D3D10:
5721 case RENDERPATH_D3D11:
5722 case RENDERPATH_SOFT:
5725 GL_CullFace(r_refdef.view.cullface_back);
5730 R_RenderView_UpdateViewVectors
5733 void R_RenderView_UpdateViewVectors(void)
5735 // break apart the view matrix into vectors for various purposes
5736 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5737 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5738 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5739 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5740 // make an inverted copy of the view matrix for tracking sprites
5741 Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5744 void R_RenderTarget_FreeUnused(qboolean force)
5747 end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5748 for (i = 0; i < end; i++)
5750 r_rendertarget_t *r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5751 // free resources for rendertargets that have not been used for a while
5752 // (note: this check is run after the frame render, so any targets used
5753 // this frame will not be affected even at low framerates)
5754 if (r && (realtime - r->lastusetime > 0.2 || force))
5757 R_Mesh_DestroyFramebufferObject(r->fbo);
5758 for (j = 0; j < sizeof(r->colortexture) / sizeof(r->colortexture[0]); j++)
5759 if (r->colortexture[j])
5760 R_FreeTexture(r->colortexture[j]);
5761 if (r->depthtexture)
5762 R_FreeTexture(r->depthtexture);
5763 Mem_ExpandableArray_FreeRecord(&r_fb.rendertargets, r);
5768 static void R_CalcTexCoordsForView(float x, float y, float w, float h, float tw, float th, float *texcoord2f)
5770 float iw = 1.0f / tw, ih = 1.0f / th, x1, y1, x2, y2;
5771 switch (vid.renderpath)
5773 case RENDERPATH_D3D9:
5774 x1 = (x + 0.5f) * iw;
5775 x2 = (x + 0.5f + w) * iw;
5776 y1 = (y + 0.5f) * ih;
5777 y2 = (y + 0.5f + h) * ih;
5783 y2 = (th - y - h) * ih;
5796 r_rendertarget_t *R_RenderTarget_Get(int texturewidth, int textureheight, textype_t depthtextype, qboolean depthisrenderbuffer, textype_t colortextype0, textype_t colortextype1, textype_t colortextype2, textype_t colortextype3)
5799 r_rendertarget_t *r = NULL;
5801 // first try to reuse an existing slot if possible
5802 end = Mem_ExpandableArray_IndexRange(&r_fb.rendertargets);
5803 for (i = 0; i < end; i++)
5805 r = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, i);
5806 if (r && r->lastusetime != realtime && r->texturewidth == texturewidth && r->textureheight == textureheight && r->depthtextype == depthtextype && r->colortextype[0] == colortextype0 && r->colortextype[1] == colortextype1 && r->colortextype[2] == colortextype2 && r->colortextype[3] == colortextype3)
5811 // no unused exact match found, so we have to make one in the first unused slot
5812 r = (r_rendertarget_t *)Mem_ExpandableArray_AllocRecord(&r_fb.rendertargets);
5813 r->texturewidth = texturewidth;
5814 r->textureheight = textureheight;
5815 r->colortextype[0] = colortextype0;
5816 r->colortextype[1] = colortextype1;
5817 r->colortextype[2] = colortextype2;
5818 r->colortextype[3] = colortextype3;
5819 r->depthtextype = depthtextype;
5820 r->depthisrenderbuffer = depthisrenderbuffer;
5821 for (j = 0; j < 4; j++)
5822 if (r->colortextype[j])
5823 r->colortexture[j] = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_%i_type%i", i, j, (int)r->colortextype[j]), r->texturewidth, r->textureheight, NULL, r->colortextype[j], TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5824 if (r->depthtextype)
5826 if (r->depthisrenderbuffer)
5827 r->depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, va(vabuf, sizeof(vabuf), "renderbuffer%i_depth_type%i", i, (int)r->depthtextype), r->texturewidth, r->textureheight, r->depthtextype);
5829 r->depthtexture = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "rendertarget%i_depth_type%i", i, j, (int)r->depthtextype), r->texturewidth, r->textureheight, NULL, r->depthtextype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5831 r->fbo = R_Mesh_CreateFramebufferObject(r->depthtexture, r->colortexture[0], r->colortexture[1], r->colortexture[2], r->colortexture[3]);
5833 r_refdef.stats[r_stat_rendertargets_used]++;
5834 r_refdef.stats[r_stat_rendertargets_pixels] += r->texturewidth * r->textureheight;
5835 r->lastusetime = realtime;
5836 R_CalcTexCoordsForView(0, 0, r->texturewidth, r->textureheight, r->texturewidth, r->textureheight, r->texcoord2f);
5840 static void R_Water_StartFrame(void)
5842 int waterwidth, waterheight;
5844 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5847 switch(vid.renderpath)
5849 case RENDERPATH_GL20:
5850 case RENDERPATH_D3D9:
5851 case RENDERPATH_D3D10:
5852 case RENDERPATH_D3D11:
5853 case RENDERPATH_SOFT:
5854 case RENDERPATH_GLES2:
5856 case RENDERPATH_GL11:
5857 case RENDERPATH_GL13:
5858 case RENDERPATH_GLES1:
5862 // set waterwidth and waterheight to the water resolution that will be
5863 // used (often less than the screen resolution for faster rendering)
5864 waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5865 waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5866 R_GetScaledViewSize(waterwidth, waterheight, &waterwidth, &waterheight);
5868 if (!r_water.integer || r_showsurfaces.integer)
5869 waterwidth = waterheight = 0;
5871 // set up variables that will be used in shader setup
5872 r_fb.water.waterwidth = waterwidth;
5873 r_fb.water.waterheight = waterheight;
5874 r_fb.water.texturewidth = waterwidth;
5875 r_fb.water.textureheight = waterheight;
5876 r_fb.water.camerawidth = waterwidth;
5877 r_fb.water.cameraheight = waterheight;
5878 r_fb.water.screenscale[0] = 0.5f;
5879 r_fb.water.screenscale[1] = 0.5f;
5880 r_fb.water.screencenter[0] = 0.5f;
5881 r_fb.water.screencenter[1] = 0.5f;
5882 r_fb.water.enabled = waterwidth != 0;
5884 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5885 r_fb.water.numwaterplanes = 0;
5888 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5890 int planeindex, bestplaneindex, vertexindex;
5891 vec3_t mins, maxs, normal, center, v, n;
5892 vec_t planescore, bestplanescore;
5894 r_waterstate_waterplane_t *p;
5895 texture_t *t = R_GetCurrentTexture(surface->texture);
5897 rsurface.texture = t;
5898 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5899 // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5900 if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5902 // average the vertex normals, find the surface bounds (after deformvertexes)
5903 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5904 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5905 VectorCopy(n, normal);
5906 VectorCopy(v, mins);
5907 VectorCopy(v, maxs);
5908 for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5910 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5911 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5912 VectorAdd(normal, n, normal);
5913 mins[0] = min(mins[0], v[0]);
5914 mins[1] = min(mins[1], v[1]);
5915 mins[2] = min(mins[2], v[2]);
5916 maxs[0] = max(maxs[0], v[0]);
5917 maxs[1] = max(maxs[1], v[1]);
5918 maxs[2] = max(maxs[2], v[2]);
5920 VectorNormalize(normal);
5921 VectorMAM(0.5f, mins, 0.5f, maxs, center);
5923 VectorCopy(normal, plane.normal);
5924 VectorNormalize(plane.normal);
5925 plane.dist = DotProduct(center, plane.normal);
5926 PlaneClassify(&plane);
5927 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5929 // skip backfaces (except if nocullface is set)
5930 // if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5932 VectorNegate(plane.normal, plane.normal);
5934 PlaneClassify(&plane);
5938 // find a matching plane if there is one
5939 bestplaneindex = -1;
5940 bestplanescore = 1048576.0f;
5941 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5943 if(p->camera_entity == t->camera_entity)
5945 planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5946 if (bestplaneindex < 0 || bestplanescore > planescore)
5948 bestplaneindex = planeindex;
5949 bestplanescore = planescore;
5953 planeindex = bestplaneindex;
5955 // if this surface does not fit any known plane rendered this frame, add one
5956 if (planeindex < 0 || bestplanescore > 0.001f)
5958 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5960 // store the new plane
5961 planeindex = r_fb.water.numwaterplanes++;
5962 p = r_fb.water.waterplanes + planeindex;
5964 // clear materialflags and pvs
5965 p->materialflags = 0;
5966 p->pvsvalid = false;
5967 p->camera_entity = t->camera_entity;
5968 VectorCopy(mins, p->mins);
5969 VectorCopy(maxs, p->maxs);
5973 // We're totally screwed.
5979 // merge mins/maxs when we're adding this surface to the plane
5980 p = r_fb.water.waterplanes + planeindex;
5981 p->mins[0] = min(p->mins[0], mins[0]);
5982 p->mins[1] = min(p->mins[1], mins[1]);
5983 p->mins[2] = min(p->mins[2], mins[2]);
5984 p->maxs[0] = max(p->maxs[0], maxs[0]);
5985 p->maxs[1] = max(p->maxs[1], maxs[1]);
5986 p->maxs[2] = max(p->maxs[2], maxs[2]);
5988 // merge this surface's materialflags into the waterplane
5989 p->materialflags |= t->currentmaterialflags;
5990 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5992 // merge this surface's PVS into the waterplane
5993 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5994 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5996 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6002 extern cvar_t r_drawparticles;
6003 extern cvar_t r_drawdecals;
6005 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int viewx, int viewy, int viewwidth, int viewheight)
6008 r_refdef_view_t originalview;
6009 r_refdef_view_t myview;
6010 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;
6011 r_waterstate_waterplane_t *p;
6013 r_rendertarget_t *rt;
6015 originalview = r_refdef.view;
6017 // lowquality hack, temporarily shut down some cvars and restore afterwards
6018 qualityreduction = r_water_lowquality.integer;
6019 if (qualityreduction > 0)
6021 if (qualityreduction >= 1)
6023 old_r_shadows = r_shadows.integer;
6024 old_r_worldrtlight = r_shadow_realtime_world.integer;
6025 old_r_dlight = r_shadow_realtime_dlight.integer;
6026 Cvar_SetValueQuick(&r_shadows, 0);
6027 Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6028 Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6030 if (qualityreduction >= 2)
6032 old_r_dynamic = r_dynamic.integer;
6033 old_r_particles = r_drawparticles.integer;
6034 old_r_decals = r_drawdecals.integer;
6035 Cvar_SetValueQuick(&r_dynamic, 0);
6036 Cvar_SetValueQuick(&r_drawparticles, 0);
6037 Cvar_SetValueQuick(&r_drawdecals, 0);
6041 for (planeindex = 0, p = r_fb.water.waterplanes; planeindex < r_fb.water.numwaterplanes; planeindex++, p++)
6043 p->rt_reflection = NULL;
6044 p->rt_refraction = NULL;
6045 p->rt_camera = NULL;
6049 r_refdef.view = originalview;
6050 r_refdef.view.showdebug = false;
6051 r_refdef.view.width = r_fb.water.waterwidth;
6052 r_refdef.view.height = r_fb.water.waterheight;
6053 r_refdef.view.useclipplane = true;
6054 myview = r_refdef.view;
6055 r_fb.water.renderingscene = true;
6056 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6058 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6061 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6063 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6064 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6066 r_refdef.view = myview;
6067 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6068 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6069 if(r_water_scissormode.integer)
6071 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6072 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6074 p->rt_reflection = NULL;
6075 p->rt_refraction = NULL;
6076 p->rt_camera = NULL;
6081 r_refdef.view.clipplane = p->plane;
6082 // reverse the cullface settings for this render
6083 r_refdef.view.cullface_front = GL_FRONT;
6084 r_refdef.view.cullface_back = GL_BACK;
6085 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6087 r_refdef.view.usecustompvs = true;
6089 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6091 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6094 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6095 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6096 GL_ScissorTest(false);
6097 R_ClearScreen(r_refdef.fogenabled);
6098 GL_ScissorTest(true);
6099 if(r_water_scissormode.integer & 2)
6100 R_View_UpdateWithScissor(myscissor);
6103 R_AnimCache_CacheVisibleEntities();
6104 if(r_water_scissormode.integer & 1)
6105 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6106 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6108 r_fb.water.hideplayer = false;
6109 p->rt_reflection = rt;
6112 // render the normal view scene and copy into texture
6113 // (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)
6114 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6116 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6117 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6119 r_refdef.view = myview;
6120 if(r_water_scissormode.integer)
6122 R_SetupView(true, rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, r_fb.water.waterwidth, r_fb.water.waterheight);
6123 if (R_ScissorForBBox(p->mins, p->maxs, myscissor))
6125 p->rt_reflection = NULL;
6126 p->rt_refraction = NULL;
6127 p->rt_camera = NULL;
6132 r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6134 r_refdef.view.clipplane = p->plane;
6135 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6136 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6138 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6140 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6141 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6142 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6143 R_RenderView_UpdateViewVectors();
6144 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6146 r_refdef.view.usecustompvs = true;
6147 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);
6151 PlaneClassify(&r_refdef.view.clipplane);
6153 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6154 GL_ScissorTest(false);
6155 R_ClearScreen(r_refdef.fogenabled);
6156 GL_ScissorTest(true);
6157 if(r_water_scissormode.integer & 2)
6158 R_View_UpdateWithScissor(myscissor);
6161 R_AnimCache_CacheVisibleEntities();
6162 if(r_water_scissormode.integer & 1)
6163 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6164 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6166 r_fb.water.hideplayer = false;
6167 p->rt_refraction = rt;
6169 else if (p->materialflags & MATERIALFLAG_CAMERA)
6171 rt = R_RenderTarget_Get(r_fb.water.waterwidth, r_fb.water.waterheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, r_fb.rt_screen->colortextype[0], TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6172 if (rt->colortexture[0] == NULL || rt->depthtexture == NULL)
6174 r_refdef.view = myview;
6176 r_refdef.view.clipplane = p->plane;
6177 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6178 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6180 r_refdef.view.width = r_fb.water.camerawidth;
6181 r_refdef.view.height = r_fb.water.cameraheight;
6182 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6183 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6184 r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6185 r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6187 if(p->camera_entity)
6189 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6190 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6193 // note: all of the view is used for displaying... so
6194 // there is no use in scissoring
6196 // reverse the cullface settings for this render
6197 r_refdef.view.cullface_front = GL_FRONT;
6198 r_refdef.view.cullface_back = GL_BACK;
6199 // also reverse the view matrix
6200 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
6201 R_RenderView_UpdateViewVectors();
6202 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6204 r_refdef.view.usecustompvs = true;
6205 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);
6208 // camera needs no clipplane
6209 r_refdef.view.useclipplane = false;
6211 PlaneClassify(&r_refdef.view.clipplane);
6213 r_fb.water.hideplayer = false;
6215 R_ResetViewRendering3D(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6216 GL_ScissorTest(false);
6217 R_ClearScreen(r_refdef.fogenabled);
6218 GL_ScissorTest(true);
6220 R_AnimCache_CacheVisibleEntities();
6221 R_RenderScene(rt->fbo, rt->depthtexture, rt->colortexture[0], 0, 0, rt->texturewidth, rt->textureheight);
6223 r_fb.water.hideplayer = false;
6228 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6229 r_fb.water.renderingscene = false;
6230 r_refdef.view = originalview;
6231 R_ResetViewRendering3D(fbo, depthtexture, colortexture, viewx, viewy, viewwidth, viewheight);
6233 R_AnimCache_CacheVisibleEntities();
6236 r_refdef.view = originalview;
6237 r_fb.water.renderingscene = false;
6238 Cvar_SetValueQuick(&r_water, 0);
6239 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
6241 // lowquality hack, restore cvars
6242 if (qualityreduction > 0)
6244 if (qualityreduction >= 1)
6246 Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6247 Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6248 Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6250 if (qualityreduction >= 2)
6252 Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6253 Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6254 Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6259 static void R_Bloom_StartFrame(void)
6261 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6262 int viewwidth, viewheight;
6263 textype_t textype = TEXTYPE_COLORBUFFER;
6265 // clear the pointers to rendertargets from last frame as they're stale
6266 r_fb.rt_screen = NULL;
6267 r_fb.rt_bloom = NULL;
6269 switch (vid.renderpath)
6271 case RENDERPATH_GL20:
6272 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6273 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6274 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6275 // for simplicity, bloom requires FBO render to texture, which basically all video drivers support now
6276 if (!vid.support.ext_framebuffer_object)
6279 case RENDERPATH_GL11:
6280 case RENDERPATH_GL13:
6281 case RENDERPATH_GLES1:
6282 return; // don't bother
6283 case RENDERPATH_GLES2:
6284 case RENDERPATH_D3D9:
6285 case RENDERPATH_D3D10:
6286 case RENDERPATH_D3D11:
6287 r_fb.usedepthtextures = false;
6289 case RENDERPATH_SOFT:
6290 r_fb.usedepthtextures = true;
6294 if (r_viewscale_fpsscaling.integer)
6296 double actualframetime;
6297 double targetframetime;
6299 actualframetime = r_refdef.lastdrawscreentime;
6300 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6301 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6302 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6303 if (r_viewscale_fpsscaling_stepsize.value > 0)
6304 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6305 viewscalefpsadjusted += adjust;
6306 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6309 viewscalefpsadjusted = 1.0f;
6311 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6313 // set bloomwidth and bloomheight to the bloom resolution that will be
6314 // used (often less than the screen resolution for faster rendering)
6315 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6316 r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6317 r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6318 r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6319 r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6321 // calculate desired texture sizes
6322 screentexturewidth = viewwidth;
6323 screentextureheight = viewheight;
6324 bloomtexturewidth = r_fb.bloomwidth;
6325 bloomtextureheight = r_fb.bloomheight;
6327 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))
6329 Cvar_SetValueQuick(&r_bloom, 0);
6330 Cvar_SetValueQuick(&r_motionblur, 0);
6331 Cvar_SetValueQuick(&r_damageblur, 0);
6334 // allocate motionblur ghost texture if needed - this is the only persistent texture and is only useful on the main view
6335 if (r_refdef.view.ismain && (r_fb.screentexturewidth != screentexturewidth || r_fb.screentextureheight != screentextureheight || r_fb.textype != textype))
6337 if (r_fb.ghosttexture)
6338 R_FreeTexture(r_fb.ghosttexture);
6339 r_fb.ghosttexture = NULL;
6341 r_fb.screentexturewidth = screentexturewidth;
6342 r_fb.screentextureheight = screentextureheight;
6343 r_fb.textype = textype;
6345 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6347 if (r_motionblur.value > 0 || r_damageblur.value > 0)
6348 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);
6349 r_fb.ghosttexture_valid = false;
6353 if (r_bloom.integer)
6355 // bloom texture is a different resolution
6356 r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6357 r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6358 r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6361 r_fb.bloomwidth = r_fb.bloomheight = 0;
6363 r_fb.rt_screen = R_RenderTarget_Get(screentexturewidth, screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8, true, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6365 r_refdef.view.clear = true;
6368 static void R_Bloom_MakeTexture(void)
6371 float xoffset, yoffset, r, brighten;
6372 float colorscale = r_bloom_colorscale.value;
6373 r_viewport_t bloomviewport;
6374 r_rendertarget_t *prev, *cur;
6375 textype_t textype = r_fb.rt_screen->colortextype[0];
6377 r_refdef.stats[r_stat_bloom]++;
6379 R_Viewport_InitOrtho(&bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6381 // scale down screen texture to the bloom texture size
6383 prev = r_fb.rt_screen;
6384 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6385 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6386 R_SetViewport(&bloomviewport);
6387 GL_CullFace(GL_NONE);
6388 GL_DepthTest(false);
6389 GL_BlendFunc(GL_ONE, GL_ZERO);
6390 GL_Color(colorscale, colorscale, colorscale, 1);
6391 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6392 // TODO: do boxfilter scale-down in shader?
6393 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, true);
6394 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6395 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6396 // we now have a properly scaled bloom image
6398 // multiply bloom image by itself as many times as desired to darken it
6399 // TODO: if people actually use this it could be done more quickly in the previous shader pass
6400 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6403 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6404 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6406 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6408 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6409 GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6410 GL_Color(1,1,1,1); // no fix factor supported here
6411 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, prev->texcoord2f);
6412 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6413 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6414 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6417 range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6418 brighten = r_bloom_brighten.value;
6419 brighten = sqrt(brighten);
6421 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6423 for (dir = 0;dir < 2;dir++)
6426 cur = R_RenderTarget_Get(r_fb.bloomwidth, r_fb.bloomheight, TEXTYPE_UNUSED, false, textype, TEXTYPE_UNUSED, TEXTYPE_UNUSED, TEXTYPE_UNUSED);
6427 R_Mesh_SetRenderTargets(cur->fbo, NULL, cur->colortexture[0], NULL, NULL, NULL);
6428 // blend on at multiple vertical offsets to achieve a vertical blur
6429 // TODO: do offset blends using GLSL
6430 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6431 GL_BlendFunc(GL_ONE, GL_ZERO);
6432 R_SetupShader_Generic(prev->colortexture[0], NULL, GL_MODULATE, 1, false, true, false);
6433 for (x = -range;x <= range;x++)
6435 if (!dir){xoffset = 0;yoffset = x;}
6436 else {xoffset = x;yoffset = 0;}
6437 xoffset /= (float)prev->texturewidth;
6438 yoffset /= (float)prev->textureheight;
6439 // compute a texcoord array with the specified x and y offset
6440 r_fb.offsettexcoord2f[0] = xoffset+prev->texcoord2f[0];
6441 r_fb.offsettexcoord2f[1] = yoffset+prev->texcoord2f[1];
6442 r_fb.offsettexcoord2f[2] = xoffset+prev->texcoord2f[2];
6443 r_fb.offsettexcoord2f[3] = yoffset+prev->texcoord2f[3];
6444 r_fb.offsettexcoord2f[4] = xoffset+prev->texcoord2f[4];
6445 r_fb.offsettexcoord2f[5] = yoffset+prev->texcoord2f[5];
6446 r_fb.offsettexcoord2f[6] = xoffset+prev->texcoord2f[6];
6447 r_fb.offsettexcoord2f[7] = yoffset+prev->texcoord2f[7];
6448 // this r value looks like a 'dot' particle, fading sharply to
6449 // black at the edges
6450 // (probably not realistic but looks good enough)
6451 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6452 //r = brighten/(range*2+1);
6453 r = brighten / (range * 2 + 1);
6455 r *= (1 - x*x/(float)((range+1)*(range+1)));
6458 GL_Color(r, r, r, 1);
6459 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6460 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6461 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6462 GL_BlendFunc(GL_ONE, GL_ONE);
6466 // now we have the bloom image, so keep track of it
6467 r_fb.rt_bloom = cur;
6470 static void R_BlendView(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
6472 dpuint64 permutation;
6473 float uservecs[4][4];
6474 rtexture_t *viewtexture;
6475 rtexture_t *bloomtexture;
6477 R_EntityMatrix(&identitymatrix);
6479 switch (vid.renderpath)
6481 case RENDERPATH_GL20:
6482 case RENDERPATH_D3D9:
6483 case RENDERPATH_D3D10:
6484 case RENDERPATH_D3D11:
6485 case RENDERPATH_SOFT:
6486 case RENDERPATH_GLES2:
6488 (r_fb.bloomwidth ? SHADERPERMUTATION_BLOOM : 0)
6489 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6490 | (!vid_gammatables_trivial ? SHADERPERMUTATION_GAMMARAMPS : 0)
6491 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6492 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6494 if(r_refdef.view.ismain && !R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6496 // declare variables
6497 float blur_factor, blur_mouseaccel, blur_velocity;
6498 static float blur_average;
6499 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6501 // set a goal for the factoring
6502 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value)
6503 / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6504 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value)
6505 / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6506 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value)
6507 + (blur_mouseaccel * r_motionblur_mousefactor.value));
6509 // from the goal, pick an averaged value between goal and last value
6510 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6511 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6513 // enforce minimum amount of blur
6514 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6516 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6518 // calculate values into a standard alpha
6519 cl.motionbluralpha = 1 - exp(-
6521 (r_motionblur.value * blur_factor / 80)
6523 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6526 max(0.0001, cl.time - cl.oldtime) // fps independent
6529 // randomization for the blur value to combat persistent ghosting
6530 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6531 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6534 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6535 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6537 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6538 GL_Color(1, 1, 1, cl.motionbluralpha);
6539 R_CalcTexCoordsForView(0, 0, viewwidth, viewheight, viewwidth, viewheight, r_fb.ghosttexcoord2f);
6540 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.ghosttexcoord2f);
6541 R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6542 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6543 r_refdef.stats[r_stat_bloom_drawpixels] += viewwidth * viewheight;
6546 // updates old view angles for next pass
6547 VectorCopy(cl.viewangles, blur_oldangles);
6549 // copy view into the ghost texture
6550 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, viewx, viewy, viewwidth, viewheight);
6551 r_refdef.stats[r_stat_bloom_copypixels] += viewwidth * viewheight;
6552 r_fb.ghosttexture_valid = true;
6555 if (r_fb.bloomwidth)
6557 // make the bloom texture
6558 R_Bloom_MakeTexture();
6561 #if _MSC_VER >= 1400
6562 #define sscanf sscanf_s
6564 memset(uservecs, 0, sizeof(uservecs));
6565 if (r_glsl_postprocess_uservec1_enable.integer)
6566 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6567 if (r_glsl_postprocess_uservec2_enable.integer)
6568 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6569 if (r_glsl_postprocess_uservec3_enable.integer)
6570 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6571 if (r_glsl_postprocess_uservec4_enable.integer)
6572 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6574 // render to the screen fbo
6575 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6576 GL_Color(1, 1, 1, 1);
6577 GL_BlendFunc(GL_ONE, GL_ZERO);
6579 viewtexture = r_fb.rt_screen->colortexture[0];
6580 bloomtexture = r_fb.rt_bloom ? r_fb.rt_bloom->colortexture[0] : NULL;
6582 if (r_rendertarget_debug.integer >= 0)
6584 r_rendertarget_t *rt = (r_rendertarget_t *)Mem_ExpandableArray_RecordAtIndex(&r_fb.rendertargets, r_rendertarget_debug.integer);
6585 if (rt && rt->colortexture[0])
6587 viewtexture = rt->colortexture[0];
6588 bloomtexture = NULL;
6592 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.rt_screen->texcoord2f, bloomtexture ? r_fb.rt_bloom->texcoord2f : NULL);
6593 switch(vid.renderpath)
6595 case RENDERPATH_GL20:
6596 case RENDERPATH_GLES2:
6597 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6598 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , viewtexture);
6599 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , bloomtexture);
6600 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6601 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]);
6602 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6603 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]);
6604 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]);
6605 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]);
6606 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]);
6607 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6608 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6609 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);
6611 case RENDERPATH_D3D9:
6613 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6614 R_Mesh_TexBind(GL20TU_FIRST , viewtexture);
6615 R_Mesh_TexBind(GL20TU_SECOND , bloomtexture);
6616 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6617 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6618 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6619 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6620 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6621 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6622 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6623 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6624 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6625 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6628 case RENDERPATH_D3D10:
6629 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6631 case RENDERPATH_D3D11:
6632 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6634 case RENDERPATH_SOFT:
6635 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6636 R_Mesh_TexBind(GL20TU_FIRST , viewtexture);
6637 R_Mesh_TexBind(GL20TU_SECOND , bloomtexture);
6638 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6639 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6640 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6641 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6642 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6643 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6644 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6645 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6646 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6647 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6652 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6653 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6655 case RENDERPATH_GL11:
6656 case RENDERPATH_GL13:
6657 case RENDERPATH_GLES1:
6658 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6660 // apply a color tint to the whole view
6661 R_ResetViewRendering2D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
6662 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6663 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6664 R_SetupShader_Generic_NoTexture(false, true);
6665 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6666 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6672 matrix4x4_t r_waterscrollmatrix;
6674 void R_UpdateFog(void)
6677 if (gamemode == GAME_NEHAHRA)
6679 if (gl_fogenable.integer)
6681 r_refdef.oldgl_fogenable = true;
6682 r_refdef.fog_density = gl_fogdensity.value;
6683 r_refdef.fog_red = gl_fogred.value;
6684 r_refdef.fog_green = gl_foggreen.value;
6685 r_refdef.fog_blue = gl_fogblue.value;
6686 r_refdef.fog_alpha = 1;
6687 r_refdef.fog_start = 0;
6688 r_refdef.fog_end = gl_skyclip.value;
6689 r_refdef.fog_height = 1<<30;
6690 r_refdef.fog_fadedepth = 128;
6692 else if (r_refdef.oldgl_fogenable)
6694 r_refdef.oldgl_fogenable = false;
6695 r_refdef.fog_density = 0;
6696 r_refdef.fog_red = 0;
6697 r_refdef.fog_green = 0;
6698 r_refdef.fog_blue = 0;
6699 r_refdef.fog_alpha = 0;
6700 r_refdef.fog_start = 0;
6701 r_refdef.fog_end = 0;
6702 r_refdef.fog_height = 1<<30;
6703 r_refdef.fog_fadedepth = 128;
6708 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6709 r_refdef.fog_start = max(0, r_refdef.fog_start);
6710 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6712 if (r_refdef.fog_density && r_drawfog.integer)
6714 r_refdef.fogenabled = true;
6715 // this is the point where the fog reaches 0.9986 alpha, which we
6716 // consider a good enough cutoff point for the texture
6717 // (0.9986 * 256 == 255.6)
6718 if (r_fog_exp2.integer)
6719 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6721 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6722 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6723 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6724 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6725 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6726 R_BuildFogHeightTexture();
6727 // fog color was already set
6728 // update the fog texture
6729 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)
6730 R_BuildFogTexture();
6731 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6732 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6735 r_refdef.fogenabled = false;
6738 if (r_refdef.fog_density)
6740 r_refdef.fogcolor[0] = r_refdef.fog_red;
6741 r_refdef.fogcolor[1] = r_refdef.fog_green;
6742 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6744 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6745 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6746 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6747 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6751 VectorCopy(r_refdef.fogcolor, fogvec);
6752 // color.rgb *= ContrastBoost * SceneBrightness;
6753 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6754 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6755 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6756 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6761 void R_UpdateVariables(void)
6765 r_refdef.scene.ambientintensity = r_ambient.value * (1.0f / 64.0f);
6767 r_refdef.farclip = r_farclip_base.value;
6768 if (r_refdef.scene.worldmodel)
6769 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6770 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6772 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6773 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6774 r_refdef.polygonfactor = 0;
6775 r_refdef.polygonoffset = 0;
6776 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6777 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6779 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6780 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6781 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6782 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6783 r_refdef.scene.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6784 if (FAKELIGHT_ENABLED)
6786 r_refdef.scene.lightmapintensity *= r_fakelight_intensity.value;
6788 else if (r_refdef.scene.worldmodel)
6790 r_refdef.scene.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6792 if (r_showsurfaces.integer)
6794 r_refdef.scene.rtworld = false;
6795 r_refdef.scene.rtworldshadows = false;
6796 r_refdef.scene.rtdlight = false;
6797 r_refdef.scene.rtdlightshadows = false;
6798 r_refdef.scene.lightmapintensity = 0;
6801 r_gpuskeletal = false;
6802 switch(vid.renderpath)
6804 case RENDERPATH_GL20:
6805 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
6806 case RENDERPATH_D3D9:
6807 case RENDERPATH_D3D10:
6808 case RENDERPATH_D3D11:
6809 case RENDERPATH_SOFT:
6810 case RENDERPATH_GLES2:
6811 if(!vid_gammatables_trivial)
6813 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6815 // build GLSL gamma texture
6816 #define RAMPWIDTH 256
6817 unsigned short ramp[RAMPWIDTH * 3];
6818 unsigned char rampbgr[RAMPWIDTH][4];
6821 r_texture_gammaramps_serial = vid_gammatables_serial;
6823 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6824 for(i = 0; i < RAMPWIDTH; ++i)
6826 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6827 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6828 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6831 if (r_texture_gammaramps)
6833 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6837 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6843 // remove GLSL gamma texture
6846 case RENDERPATH_GL11:
6847 case RENDERPATH_GL13:
6848 case RENDERPATH_GLES1:
6853 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6854 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6860 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6861 if( scenetype != r_currentscenetype ) {
6862 // store the old scenetype
6863 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6864 r_currentscenetype = scenetype;
6865 // move in the new scene
6866 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6875 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6877 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6878 if( scenetype == r_currentscenetype ) {
6879 return &r_refdef.scene;
6881 return &r_scenes_store[ scenetype ];
6885 static int R_SortEntities_Compare(const void *ap, const void *bp)
6887 const entity_render_t *a = *(const entity_render_t **)ap;
6888 const entity_render_t *b = *(const entity_render_t **)bp;
6891 if(a->model < b->model)
6893 if(a->model > b->model)
6897 // TODO possibly calculate the REAL skinnum here first using
6899 if(a->skinnum < b->skinnum)
6901 if(a->skinnum > b->skinnum)
6904 // everything we compared is equal
6907 static void R_SortEntities(void)
6909 // below or equal 2 ents, sorting never gains anything
6910 if(r_refdef.scene.numentities <= 2)
6913 qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6921 int dpsoftrast_test;
6922 extern cvar_t r_shadow_bouncegrid;
6923 extern cvar_t v_isometric;
6924 extern void V_MakeViewIsometric(void);
6925 void R_RenderView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, int x, int y, int width, int height)
6927 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6929 rtexture_t *viewdepthtexture = NULL;
6930 rtexture_t *viewcolortexture = NULL;
6931 int viewx = r_refdef.view.x, viewy = r_refdef.view.y, viewwidth = r_refdef.view.width, viewheight = r_refdef.view.height;
6933 dpsoftrast_test = r_test.integer;
6935 if (r_timereport_active)
6936 R_TimeReport("start");
6937 r_textureframe++; // used only by R_GetCurrentTexture
6938 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
6940 if(R_CompileShader_CheckStaticParms())
6943 if (!r_drawentities.integer)
6944 r_refdef.scene.numentities = 0;
6945 else if (r_sortentities.integer)
6948 R_AnimCache_ClearCache();
6950 /* adjust for stereo display */
6951 if(R_Stereo_Active())
6953 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);
6954 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6957 if (r_refdef.view.isoverlay)
6959 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6960 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6961 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6962 R_TimeReport("depthclear");
6964 r_refdef.view.showdebug = false;
6966 r_fb.water.enabled = false;
6967 r_fb.water.numwaterplanes = 0;
6969 R_RenderScene(0, NULL, NULL, r_refdef.view.x, r_refdef.view.y, r_refdef.view.width, r_refdef.view.height);
6971 r_refdef.view.matrix = originalmatrix;
6977 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6979 r_refdef.view.matrix = originalmatrix;
6983 if (v_isometric.integer && r_refdef.view.ismain)
6984 V_MakeViewIsometric();
6986 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6988 if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6989 // in sRGB fallback, behave similar to true sRGB: convert this
6990 // value from linear to sRGB
6991 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6993 R_RenderView_UpdateViewVectors();
6995 R_Shadow_UpdateWorldLightSelection();
6997 // this will set up r_fb.rt_screen
6998 R_Bloom_StartFrame();
7000 // apply bloom brightness offset
7002 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7004 // R_Bloom_StartFrame probably set up an fbo for us to render into, it will be rendered to the window later in R_BlendView
7007 viewfbo = r_fb.rt_screen->fbo;
7008 viewdepthtexture = r_fb.rt_screen->depthtexture;
7009 viewcolortexture = r_fb.rt_screen->colortexture[0];
7013 viewheight = height;
7016 R_Water_StartFrame();
7019 if (r_timereport_active)
7020 R_TimeReport("viewsetup");
7022 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7024 // clear the whole fbo every frame - otherwise the driver will consider
7025 // it to be an inter-frame texture and stall in multi-gpu configurations
7027 GL_ScissorTest(false);
7028 R_ClearScreen(r_refdef.fogenabled);
7029 if (r_timereport_active)
7030 R_TimeReport("viewclear");
7032 r_refdef.view.clear = true;
7034 r_refdef.view.showdebug = true;
7037 if (r_timereport_active)
7038 R_TimeReport("visibility");
7040 R_AnimCache_CacheVisibleEntities();
7041 if (r_timereport_active)
7042 R_TimeReport("animcache");
7044 R_Shadow_UpdateBounceGridTexture();
7045 if (r_timereport_active && r_shadow_bouncegrid.integer)
7046 R_TimeReport("bouncegrid");
7048 r_fb.water.numwaterplanes = 0;
7049 if (r_fb.water.enabled)
7050 R_RenderWaterPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7052 // for the actual view render we use scissoring a fair amount, so scissor
7053 // test needs to be on
7055 GL_ScissorTest(true);
7056 GL_Scissor(viewx, viewy, viewwidth, viewheight);
7057 R_RenderScene(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7058 r_fb.water.numwaterplanes = 0;
7060 // postprocess uses textures that are not aligned with the viewport we're rendering, so no scissoring
7061 GL_ScissorTest(false);
7063 R_BlendView(fbo, depthtexture, colortexture, x, y, width, height);
7064 if (r_timereport_active)
7065 R_TimeReport("blendview");
7067 r_refdef.view.matrix = originalmatrix;
7072 void R_RenderWaterPlanes(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7074 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7076 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7077 if (r_timereport_active)
7078 R_TimeReport("waterworld");
7081 // don't let sound skip if going slow
7082 if (r_refdef.scene.extraupdate)
7085 R_DrawModelsAddWaterPlanes();
7086 if (r_timereport_active)
7087 R_TimeReport("watermodels");
7089 if (r_fb.water.numwaterplanes)
7091 R_Water_ProcessPlanes(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7092 if (r_timereport_active)
7093 R_TimeReport("waterscenes");
7097 extern cvar_t cl_locs_show;
7098 static void R_DrawLocs(void);
7099 static void R_DrawEntityBBoxes(prvm_prog_t *prog);
7100 static void R_DrawModelDecals(void);
7101 extern cvar_t cl_decals_newsystem;
7102 extern qboolean r_shadow_usingdeferredprepass;
7103 extern int r_shadow_shadowmapatlas_modelshadows_size;
7104 void R_RenderScene(int viewfbo, rtexture_t *viewdepthtexture, rtexture_t *viewcolortexture, int viewx, int viewy, int viewwidth, int viewheight)
7106 qboolean shadowmapping = false;
7108 if (r_timereport_active)
7109 R_TimeReport("beginscene");
7111 r_refdef.stats[r_stat_renders]++;
7115 // don't let sound skip if going slow
7116 if (r_refdef.scene.extraupdate)
7119 R_MeshQueue_BeginScene();
7123 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);
7125 if (r_timereport_active)
7126 R_TimeReport("skystartframe");
7128 if (cl.csqc_vidvars.drawworld)
7130 // don't let sound skip if going slow
7131 if (r_refdef.scene.extraupdate)
7134 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7136 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7137 if (r_timereport_active)
7138 R_TimeReport("worldsky");
7141 if (R_DrawBrushModelsSky() && r_timereport_active)
7142 R_TimeReport("bmodelsky");
7144 if (skyrendermasked && skyrenderlater)
7146 // we have to force off the water clipping plane while rendering sky
7147 R_SetupView(false, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7149 R_SetupView(true, viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7150 if (r_timereport_active)
7151 R_TimeReport("sky");
7155 // save the framebuffer info for R_Shadow_RenderMode_Reset during this view render
7156 r_shadow_viewfbo = viewfbo;
7157 r_shadow_viewdepthtexture = viewdepthtexture;
7158 r_shadow_viewcolortexture = viewcolortexture;
7159 r_shadow_viewx = viewx;
7160 r_shadow_viewy = viewy;
7161 r_shadow_viewwidth = viewwidth;
7162 r_shadow_viewheight = viewheight;
7164 R_Shadow_PrepareModelShadows();
7165 R_Shadow_PrepareLights();
7166 if (r_timereport_active)
7167 R_TimeReport("preparelights");
7169 // render all the shadowmaps that will be used for this view
7170 shadowmapping = R_Shadow_ShadowMappingEnabled();
7171 if (shadowmapping || r_shadow_shadowmapatlas_modelshadows_size)
7173 R_Shadow_DrawShadowMaps();
7174 if (r_timereport_active)
7175 R_TimeReport("shadowmaps");
7178 // render prepass deferred lighting if r_shadow_deferred is on, this produces light buffers that will be sampled in forward pass
7179 if (r_shadow_usingdeferredprepass)
7180 R_Shadow_DrawPrepass();
7182 // now we begin the forward pass of the view render
7183 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7185 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7186 if (r_timereport_active)
7187 R_TimeReport("worlddepth");
7189 if (r_depthfirst.integer >= 2)
7191 R_DrawModelsDepth();
7192 if (r_timereport_active)
7193 R_TimeReport("modeldepth");
7196 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7198 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7199 if (r_timereport_active)
7200 R_TimeReport("world");
7203 // don't let sound skip if going slow
7204 if (r_refdef.scene.extraupdate)
7208 if (r_timereport_active)
7209 R_TimeReport("models");
7211 // don't let sound skip if going slow
7212 if (r_refdef.scene.extraupdate)
7215 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7217 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7218 R_Shadow_DrawModelShadows();
7219 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7220 // don't let sound skip if going slow
7221 if (r_refdef.scene.extraupdate)
7225 if (!r_shadow_usingdeferredprepass)
7227 R_Shadow_DrawLights();
7228 if (r_timereport_active)
7229 R_TimeReport("rtlights");
7232 // don't let sound skip if going slow
7233 if (r_refdef.scene.extraupdate)
7236 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.scene.lightmapintensity > 0)
7238 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7239 R_Shadow_DrawModelShadows();
7240 R_ResetViewRendering3D(viewfbo, viewdepthtexture, viewcolortexture, viewx, viewy, viewwidth, viewheight);
7241 // don't let sound skip if going slow
7242 if (r_refdef.scene.extraupdate)
7246 if (cl.csqc_vidvars.drawworld)
7248 if (cl_decals_newsystem.integer)
7250 R_DrawModelDecals();
7251 if (r_timereport_active)
7252 R_TimeReport("modeldecals");
7257 if (r_timereport_active)
7258 R_TimeReport("decals");
7262 if (r_timereport_active)
7263 R_TimeReport("particles");
7266 if (r_timereport_active)
7267 R_TimeReport("explosions");
7270 if (r_refdef.view.showdebug)
7272 if (cl_locs_show.integer)
7275 if (r_timereport_active)
7276 R_TimeReport("showlocs");
7279 if (r_drawportals.integer)
7282 if (r_timereport_active)
7283 R_TimeReport("portals");
7286 if (r_showbboxes_client.value > 0)
7288 R_DrawEntityBBoxes(CLVM_prog);
7289 if (r_timereport_active)
7290 R_TimeReport("clbboxes");
7292 if (r_showbboxes.value > 0)
7294 R_DrawEntityBBoxes(SVVM_prog);
7295 if (r_timereport_active)
7296 R_TimeReport("svbboxes");
7300 if (r_transparent.integer)
7302 R_MeshQueue_RenderTransparent();
7303 if (r_timereport_active)
7304 R_TimeReport("drawtrans");
7307 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))
7309 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7310 if (r_timereport_active)
7311 R_TimeReport("worlddebug");
7312 R_DrawModelsDebug();
7313 if (r_timereport_active)
7314 R_TimeReport("modeldebug");
7317 if (cl.csqc_vidvars.drawworld)
7319 R_Shadow_DrawCoronas();
7320 if (r_timereport_active)
7321 R_TimeReport("coronas");
7326 GL_DepthTest(false);
7327 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7328 GL_Color(1, 1, 1, 1);
7329 qglBegin(GL_POLYGON);
7330 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7331 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7332 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7333 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7335 qglBegin(GL_POLYGON);
7336 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]);
7337 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]);
7338 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]);
7339 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]);
7341 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7345 // don't let sound skip if going slow
7346 if (r_refdef.scene.extraupdate)
7350 static const unsigned short bboxelements[36] =
7360 #define BBOXEDGES 13
7361 static const float bboxedges[BBOXEDGES][6] =
7364 { 0, 0, 0, 1, 1, 1 },
7366 { 0, 0, 0, 0, 1, 0 },
7367 { 0, 0, 0, 1, 0, 0 },
7368 { 0, 1, 0, 1, 1, 0 },
7369 { 1, 0, 0, 1, 1, 0 },
7371 { 0, 0, 1, 0, 1, 1 },
7372 { 0, 0, 1, 1, 0, 1 },
7373 { 0, 1, 1, 1, 1, 1 },
7374 { 1, 0, 1, 1, 1, 1 },
7376 { 0, 0, 0, 0, 0, 1 },
7377 { 1, 0, 0, 1, 0, 1 },
7378 { 0, 1, 0, 0, 1, 1 },
7379 { 1, 1, 0, 1, 1, 1 },
7382 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7384 int numvertices = BBOXEDGES * 8;
7385 float vertex3f[BBOXEDGES * 8 * 3], color4f[BBOXEDGES * 8 * 4];
7386 int numtriangles = BBOXEDGES * 12;
7387 unsigned short elements[BBOXEDGES * 36];
7389 float *v, *c, f1, f2, edgemins[3], edgemaxs[3];
7391 RSurf_ActiveModelEntity(r_refdef.scene.worldentity, false, false, false);
7393 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7394 GL_DepthMask(false);
7395 GL_DepthRange(0, 1);
7396 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7398 for (edge = 0; edge < BBOXEDGES; edge++)
7400 for (i = 0; i < 3; i++)
7402 edgemins[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][i] - 0.25f;
7403 edgemaxs[i] = mins[i] + (maxs[i] - mins[i]) * bboxedges[edge][3 + i] + 0.25f;
7405 vertex3f[edge * 24 + 0] = edgemins[0]; vertex3f[edge * 24 + 1] = edgemins[1]; vertex3f[edge * 24 + 2] = edgemins[2];
7406 vertex3f[edge * 24 + 3] = edgemaxs[0]; vertex3f[edge * 24 + 4] = edgemins[1]; vertex3f[edge * 24 + 5] = edgemins[2];
7407 vertex3f[edge * 24 + 6] = edgemins[0]; vertex3f[edge * 24 + 7] = edgemaxs[1]; vertex3f[edge * 24 + 8] = edgemins[2];
7408 vertex3f[edge * 24 + 9] = edgemaxs[0]; vertex3f[edge * 24 + 10] = edgemaxs[1]; vertex3f[edge * 24 + 11] = edgemins[2];
7409 vertex3f[edge * 24 + 12] = edgemins[0]; vertex3f[edge * 24 + 13] = edgemins[1]; vertex3f[edge * 24 + 14] = edgemaxs[2];
7410 vertex3f[edge * 24 + 15] = edgemaxs[0]; vertex3f[edge * 24 + 16] = edgemins[1]; vertex3f[edge * 24 + 17] = edgemaxs[2];
7411 vertex3f[edge * 24 + 18] = edgemins[0]; vertex3f[edge * 24 + 19] = edgemaxs[1]; vertex3f[edge * 24 + 20] = edgemaxs[2];
7412 vertex3f[edge * 24 + 21] = edgemaxs[0]; vertex3f[edge * 24 + 22] = edgemaxs[1]; vertex3f[edge * 24 + 23] = edgemaxs[2];
7413 for (i = 0; i < 36; i++)
7414 elements[edge * 36 + i] = edge * 8 + bboxelements[i];
7416 R_FillColors(color4f, numvertices, cr, cg, cb, ca);
7417 if (r_refdef.fogenabled)
7419 for (i = 0, v = vertex3f, c = color4f; i < numvertices; i++, v += 3, c += 4)
7421 f1 = RSurf_FogVertex(v);
7423 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7424 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7425 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7428 R_Mesh_PrepareVertices_Generic_Arrays(numvertices, vertex3f, color4f, NULL);
7429 R_Mesh_ResetTextureState();
7430 R_SetupShader_Generic_NoTexture(false, false);
7431 R_Mesh_Draw(0, numvertices, 0, numtriangles, NULL, NULL, 0, elements, NULL, 0);
7434 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7436 // hacky overloading of the parameters
7437 prvm_prog_t *prog = (prvm_prog_t *)rtlight;
7440 prvm_edict_t *edict;
7442 GL_CullFace(GL_NONE);
7443 R_SetupShader_Generic_NoTexture(false, false);
7445 for (i = 0;i < numsurfaces;i++)
7447 edict = PRVM_EDICT_NUM(surfacelist[i]);
7448 switch ((int)PRVM_serveredictfloat(edict, solid))
7450 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7451 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7452 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7453 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7454 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7455 case SOLID_CORPSE: Vector4Set(color, 1, 0.5, 0, 0.05);break;
7456 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7458 if (prog == CLVM_prog)
7459 color[3] *= r_showbboxes_client.value;
7461 color[3] *= r_showbboxes.value;
7462 color[3] = bound(0, color[3], 1);
7463 GL_DepthTest(!r_showdisabledepthtest.integer);
7464 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7468 static void R_DrawEntityBBoxes(prvm_prog_t *prog)
7471 prvm_edict_t *edict;
7477 for (i = 0; i < prog->num_edicts; i++)
7479 edict = PRVM_EDICT_NUM(i);
7480 if (edict->priv.server->free)
7482 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7483 if (PRVM_serveredictedict(edict, tag_entity) != 0)
7485 if (PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7487 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7488 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)prog);
7492 static const int nomodelelement3i[24] =
7504 static const unsigned short nomodelelement3s[24] =
7516 static const float nomodelvertex3f[6*3] =
7526 static const float nomodelcolor4f[6*4] =
7528 0.0f, 0.0f, 0.5f, 1.0f,
7529 0.0f, 0.0f, 0.5f, 1.0f,
7530 0.0f, 0.5f, 0.0f, 1.0f,
7531 0.0f, 0.5f, 0.0f, 1.0f,
7532 0.5f, 0.0f, 0.0f, 1.0f,
7533 0.5f, 0.0f, 0.0f, 1.0f
7536 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7542 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);
7544 // this is only called once per entity so numsurfaces is always 1, and
7545 // surfacelist is always {0}, so this code does not handle batches
7547 if (rsurface.ent_flags & RENDER_ADDITIVE)
7549 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7550 GL_DepthMask(false);
7552 else if (ent->alpha < 1)
7554 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7555 GL_DepthMask(false);
7559 GL_BlendFunc(GL_ONE, GL_ZERO);
7562 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7563 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7564 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7565 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7566 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7567 for (i = 0, c = color4f;i < 6;i++, c += 4)
7569 c[0] *= ent->render_fullbright[0] * r_refdef.view.colorscale;
7570 c[1] *= ent->render_fullbright[1] * r_refdef.view.colorscale;
7571 c[2] *= ent->render_fullbright[2] * r_refdef.view.colorscale;
7574 if (r_refdef.fogenabled)
7576 for (i = 0, c = color4f;i < 6;i++, c += 4)
7578 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7580 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7581 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7582 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7585 // R_Mesh_ResetTextureState();
7586 R_SetupShader_Generic_NoTexture(false, false);
7587 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7588 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7591 void R_DrawNoModel(entity_render_t *ent)
7594 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7595 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7596 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7598 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7601 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7603 vec3_t right1, right2, diff, normal;
7605 VectorSubtract (org2, org1, normal);
7607 // calculate 'right' vector for start
7608 VectorSubtract (r_refdef.view.origin, org1, diff);
7609 CrossProduct (normal, diff, right1);
7610 VectorNormalize (right1);
7612 // calculate 'right' vector for end
7613 VectorSubtract (r_refdef.view.origin, org2, diff);
7614 CrossProduct (normal, diff, right2);
7615 VectorNormalize (right2);
7617 vert[ 0] = org1[0] + width * right1[0];
7618 vert[ 1] = org1[1] + width * right1[1];
7619 vert[ 2] = org1[2] + width * right1[2];
7620 vert[ 3] = org1[0] - width * right1[0];
7621 vert[ 4] = org1[1] - width * right1[1];
7622 vert[ 5] = org1[2] - width * right1[2];
7623 vert[ 6] = org2[0] - width * right2[0];
7624 vert[ 7] = org2[1] - width * right2[1];
7625 vert[ 8] = org2[2] - width * right2[2];
7626 vert[ 9] = org2[0] + width * right2[0];
7627 vert[10] = org2[1] + width * right2[1];
7628 vert[11] = org2[2] + width * right2[2];
7631 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)
7633 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7634 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7635 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7636 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7637 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7638 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7639 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7640 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7641 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7642 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7643 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7644 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7647 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7652 VectorSet(v, x, y, z);
7653 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7654 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7656 if (i == mesh->numvertices)
7658 if (mesh->numvertices < mesh->maxvertices)
7660 VectorCopy(v, vertex3f);
7661 mesh->numvertices++;
7663 return mesh->numvertices;
7669 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7673 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7674 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7675 e = mesh->element3i + mesh->numtriangles * 3;
7676 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7678 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7679 if (mesh->numtriangles < mesh->maxtriangles)
7684 mesh->numtriangles++;
7686 element[1] = element[2];
7690 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7694 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7695 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7696 e = mesh->element3i + mesh->numtriangles * 3;
7697 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7699 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7700 if (mesh->numtriangles < mesh->maxtriangles)
7705 mesh->numtriangles++;
7707 element[1] = element[2];
7711 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7712 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7714 int planenum, planenum2;
7717 mplane_t *plane, *plane2;
7719 double temppoints[2][256*3];
7720 // figure out how large a bounding box we need to properly compute this brush
7722 for (w = 0;w < numplanes;w++)
7723 maxdist = max(maxdist, fabs(planes[w].dist));
7724 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7725 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7726 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7730 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7731 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7733 if (planenum2 == planenum)
7735 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);
7738 if (tempnumpoints < 3)
7740 // generate elements forming a triangle fan for this polygon
7741 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7745 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)
7747 texturelayer_t *layer;
7748 layer = t->currentlayers + t->currentnumlayers++;
7750 layer->depthmask = depthmask;
7751 layer->blendfunc1 = blendfunc1;
7752 layer->blendfunc2 = blendfunc2;
7753 layer->texture = texture;
7754 layer->texmatrix = *matrix;
7755 layer->color[0] = r;
7756 layer->color[1] = g;
7757 layer->color[2] = b;
7758 layer->color[3] = a;
7761 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7763 if(parms[0] == 0 && parms[1] == 0)
7765 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7766 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7771 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7774 index = parms[2] + rsurface.shadertime * parms[3];
7775 index -= floor(index);
7776 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7779 case Q3WAVEFUNC_NONE:
7780 case Q3WAVEFUNC_NOISE:
7781 case Q3WAVEFUNC_COUNT:
7784 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7785 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7786 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7787 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7788 case Q3WAVEFUNC_TRIANGLE:
7790 f = index - floor(index);
7803 f = parms[0] + parms[1] * f;
7804 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7805 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7809 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7816 matrix4x4_t matrix, temp;
7817 // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
7818 // it's better to have one huge fixup every 9 hours than gradual
7819 // degradation over time which looks consistently bad after many hours.
7821 // tcmod scroll in particular suffers from this degradation which can't be
7822 // effectively worked around even with floor() tricks because we don't
7823 // know if tcmod scroll is the last tcmod being applied, and for clampmap
7824 // a workaround involving floor() would be incorrect anyway...
7825 shadertime = rsurface.shadertime;
7826 if (shadertime >= 32768.0f)
7827 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
7828 switch(tcmod->tcmod)
7832 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7833 matrix = r_waterscrollmatrix;
7835 matrix = identitymatrix;
7837 case Q3TCMOD_ENTITYTRANSLATE:
7838 // this is used in Q3 to allow the gamecode to control texcoord
7839 // scrolling on the entity, which is not supported in darkplaces yet.
7840 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7842 case Q3TCMOD_ROTATE:
7843 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7844 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7845 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7848 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7850 case Q3TCMOD_SCROLL:
7851 // this particular tcmod is a "bug for bug" compatible one with regards to
7852 // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
7853 // specifically did the wrapping and so we must mimic that...
7854 offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7855 offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7856 Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7858 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7859 w = (int) tcmod->parms[0];
7860 h = (int) tcmod->parms[1];
7861 f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7863 idx = (int) floor(f * w * h);
7864 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7866 case Q3TCMOD_STRETCH:
7867 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7868 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7870 case Q3TCMOD_TRANSFORM:
7871 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7872 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7873 VectorSet(tcmat + 6, 0 , 0 , 1);
7874 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7875 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7877 case Q3TCMOD_TURBULENT:
7878 // this is handled in the RSurf_PrepareVertices function
7879 matrix = identitymatrix;
7883 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7886 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7888 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7889 char name[MAX_QPATH];
7890 skinframe_t *skinframe;
7891 unsigned char pixels[296*194];
7892 strlcpy(cache->name, skinname, sizeof(cache->name));
7893 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7894 if (developer_loading.integer)
7895 Con_Printf("loading %s\n", name);
7896 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7897 if (!skinframe || !skinframe->base)
7900 fs_offset_t filesize;
7902 f = FS_LoadFile(name, tempmempool, true, &filesize);
7905 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7906 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7910 cache->skinframe = skinframe;
7913 texture_t *R_GetCurrentTexture(texture_t *t)
7916 const entity_render_t *ent = rsurface.entity;
7917 dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7918 q3shaderinfo_layer_tcmod_t *tcmod;
7919 float specularscale = 0.0f;
7921 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7922 return t->currentframe;
7923 t->update_lastrenderframe = r_textureframe;
7924 t->update_lastrenderentity = (void *)ent;
7926 if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7927 t->camera_entity = ent->entitynumber;
7929 t->camera_entity = 0;
7931 // switch to an alternate material if this is a q1bsp animated material
7933 texture_t *texture = t;
7934 int s = rsurface.ent_skinnum;
7935 if ((unsigned int)s >= (unsigned int)model->numskins)
7937 if (model->skinscenes)
7939 if (model->skinscenes[s].framecount > 1)
7940 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7942 s = model->skinscenes[s].firstframe;
7945 t = t + s * model->num_surfaces;
7948 // use an alternate animation if the entity's frame is not 0,
7949 // and only if the texture has an alternate animation
7950 if (t->animated == 2) // q2bsp
7951 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
7952 else if (rsurface.ent_alttextures && t->anim_total[1])
7953 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7955 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7957 texture->currentframe = t;
7960 // update currentskinframe to be a qw skin or animation frame
7961 if (rsurface.ent_qwskin >= 0)
7963 i = rsurface.ent_qwskin;
7964 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7966 r_qwskincache_size = cl.maxclients;
7968 Mem_Free(r_qwskincache);
7969 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7971 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7972 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7973 t->currentskinframe = r_qwskincache[i].skinframe;
7974 if (t->materialshaderpass && t->currentskinframe == NULL)
7975 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7977 else if (t->materialshaderpass && t->materialshaderpass->numframes >= 2)
7978 t->currentskinframe = t->materialshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->materialshaderpass->framerate, t->materialshaderpass->numframes)];
7979 if (t->backgroundshaderpass && t->backgroundshaderpass->numframes >= 2)
7980 t->backgroundcurrentskinframe = t->backgroundshaderpass->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundshaderpass->framerate, t->backgroundshaderpass->numframes)];
7982 t->currentmaterialflags = t->basematerialflags;
7983 t->currentalpha = rsurface.entity->alpha * t->basealpha;
7984 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7985 t->currentalpha *= r_wateralpha.value;
7986 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7987 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7988 if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7989 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7991 // decide on which type of lighting to use for this surface
7992 if (rsurface.entity->render_modellight_forced)
7993 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7994 if (rsurface.entity->render_rtlight_disabled)
7995 t->currentmaterialflags |= MATERIALFLAG_NORTLIGHT;
7996 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND && !(R_BlendFuncFlags(t->customblendfunc[0], t->customblendfunc[1]) & BLENDFUNC_ALLOWS_COLORMOD))
7998 // some CUSTOMBLEND blendfuncs are too weird, we have to ignore colormod and view colorscale
7999 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT;
8000 for (q = 0; q < 3; q++)
8002 t->render_glowmod[q] = rsurface.entity->glowmod[q];
8003 t->render_modellight_lightdir[q] = q == 2;
8004 t->render_modellight_ambient[q] = 1;
8005 t->render_modellight_diffuse[q] = 0;
8006 t->render_modellight_specular[q] = 0;
8007 t->render_lightmap_ambient[q] = 0;
8008 t->render_lightmap_diffuse[q] = 0;
8009 t->render_lightmap_specular[q] = 0;
8010 t->render_rtlight_diffuse[q] = 0;
8011 t->render_rtlight_specular[q] = 0;
8014 else if ((t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || !(rsurface.ent_flags & RENDER_LIGHT))
8016 // fullbright is basically MATERIALFLAG_MODELLIGHT but with ambient locked to 1,1,1 and no shading
8017 t->currentmaterialflags = t->currentmaterialflags | MATERIALFLAG_NORTLIGHT | MATERIALFLAG_MODELLIGHT;
8018 for (q = 0; q < 3; q++)
8020 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8021 t->render_modellight_ambient[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8022 t->render_modellight_lightdir[q] = q == 2;
8023 t->render_modellight_diffuse[q] = 0;
8024 t->render_modellight_specular[q] = 0;
8025 t->render_lightmap_ambient[q] = 0;
8026 t->render_lightmap_diffuse[q] = 0;
8027 t->render_lightmap_specular[q] = 0;
8028 t->render_rtlight_diffuse[q] = 0;
8029 t->render_rtlight_specular[q] = 0;
8032 else if (FAKELIGHT_ENABLED)
8034 // no modellight if using fakelight for the map
8035 t->currentmaterialflags = (t->currentmaterialflags | MATERIALFLAG_NORTLIGHT) & ~(MATERIALFLAG_MODELLIGHT);
8036 for (q = 0; q < 3; q++)
8038 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8039 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8040 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8041 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8042 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8043 t->render_lightmap_ambient[q] = 0;
8044 t->render_lightmap_diffuse[q] = 0;
8045 t->render_lightmap_specular[q] = 0;
8046 t->render_rtlight_diffuse[q] = 0;
8047 t->render_rtlight_specular[q] = 0;
8050 else if ((rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT)) || rsurface.modeltexcoordlightmap2f == NULL)
8052 // ambient + single direction light (modellight)
8053 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8054 for (q = 0; q < 3; q++)
8056 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8057 t->render_modellight_lightdir[q] = rsurface.entity->render_modellight_lightdir[q];
8058 t->render_modellight_ambient[q] = rsurface.entity->render_modellight_ambient[q] * r_refdef.view.colorscale;
8059 t->render_modellight_diffuse[q] = rsurface.entity->render_modellight_diffuse[q] * r_refdef.view.colorscale;
8060 t->render_modellight_specular[q] = rsurface.entity->render_modellight_specular[q] * r_refdef.view.colorscale;
8061 t->render_lightmap_ambient[q] = 0;
8062 t->render_lightmap_diffuse[q] = 0;
8063 t->render_lightmap_specular[q] = 0;
8064 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8065 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8070 // lightmap - 2x diffuse and specular brightness because bsp files have 0-2 colors as 0-1
8071 for (q = 0; q < 3; q++)
8073 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8074 t->render_modellight_lightdir[q] = q == 2;
8075 t->render_modellight_ambient[q] = 0;
8076 t->render_modellight_diffuse[q] = 0;
8077 t->render_modellight_specular[q] = 0;
8078 t->render_lightmap_ambient[q] = rsurface.entity->render_lightmap_ambient[q] * r_refdef.view.colorscale;
8079 t->render_lightmap_diffuse[q] = rsurface.entity->render_lightmap_diffuse[q] * 2 * r_refdef.view.colorscale;
8080 t->render_lightmap_specular[q] = rsurface.entity->render_lightmap_specular[q] * 2 * r_refdef.view.colorscale;
8081 t->render_rtlight_diffuse[q] = rsurface.entity->render_rtlight_diffuse[q] * r_refdef.view.colorscale;
8082 t->render_rtlight_specular[q] = rsurface.entity->render_rtlight_specular[q] * r_refdef.view.colorscale;
8086 if (t->currentmaterialflags & MATERIALFLAG_VERTEXCOLOR)
8088 // since MATERIALFLAG_VERTEXCOLOR uses the lightmapcolor4f vertex
8089 // attribute, we punt it to the lightmap path and hope for the best,
8090 // but lighting doesn't work.
8092 // FIXME: this is fine for effects but CSQC polygons should be subject
8094 t->currentmaterialflags &= ~MATERIALFLAG_MODELLIGHT;
8095 for (q = 0; q < 3; q++)
8097 t->render_glowmod[q] = rsurface.entity->render_glowmod[q] * r_refdef.view.colorscale;
8098 t->render_modellight_lightdir[q] = q == 2;
8099 t->render_modellight_ambient[q] = 0;
8100 t->render_modellight_diffuse[q] = 0;
8101 t->render_modellight_specular[q] = 0;
8102 t->render_lightmap_ambient[q] = 0;
8103 t->render_lightmap_diffuse[q] = rsurface.entity->render_fullbright[q] * r_refdef.view.colorscale;
8104 t->render_lightmap_specular[q] = 0;
8105 t->render_rtlight_diffuse[q] = 0;
8106 t->render_rtlight_specular[q] = 0;
8110 for (q = 0; q < 3; q++)
8112 t->render_colormap_pants[q] = rsurface.entity->colormap_pantscolor[q];
8113 t->render_colormap_shirt[q] = rsurface.entity->colormap_shirtcolor[q];
8116 if (rsurface.ent_flags & RENDER_ADDITIVE)
8117 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8118 else if (t->currentalpha < 1)
8119 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8120 // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8121 if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8122 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8123 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8124 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8125 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8126 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8127 if (t->backgroundshaderpass)
8128 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8129 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8131 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8132 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8135 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8136 if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8138 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8139 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8141 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8142 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8144 // there is no tcmod
8145 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8147 t->currenttexmatrix = r_waterscrollmatrix;
8148 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8150 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8152 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8153 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8156 if (t->materialshaderpass)
8157 for (i = 0, tcmod = t->materialshaderpass->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8158 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8160 t->colormapping = VectorLength2(t->render_colormap_pants) + VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f);
8161 if (t->currentskinframe->qpixels)
8162 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8163 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8164 if (!t->basetexture)
8165 t->basetexture = r_texture_notexture;
8166 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8167 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8168 t->nmaptexture = t->currentskinframe->nmap;
8169 if (!t->nmaptexture)
8170 t->nmaptexture = r_texture_blanknormalmap;
8171 t->glosstexture = r_texture_black;
8172 t->glowtexture = t->currentskinframe->glow;
8173 t->fogtexture = t->currentskinframe->fog;
8174 t->reflectmasktexture = t->currentskinframe->reflect;
8175 if (t->backgroundshaderpass)
8177 for (i = 0, tcmod = t->backgroundshaderpass->tcmods; i < Q3MAXTCMODS && tcmod->tcmod; i++, tcmod++)
8178 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8179 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8180 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8181 t->backgroundglosstexture = r_texture_black;
8182 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8183 if (!t->backgroundnmaptexture)
8184 t->backgroundnmaptexture = r_texture_blanknormalmap;
8185 // make sure that if glow is going to be used, both textures are not NULL
8186 if (!t->backgroundglowtexture && t->glowtexture)
8187 t->backgroundglowtexture = r_texture_black;
8188 if (!t->glowtexture && t->backgroundglowtexture)
8189 t->glowtexture = r_texture_black;
8193 t->backgroundbasetexture = r_texture_white;
8194 t->backgroundnmaptexture = r_texture_blanknormalmap;
8195 t->backgroundglosstexture = r_texture_black;
8196 t->backgroundglowtexture = NULL;
8198 t->specularpower = r_shadow_glossexponent.value;
8199 // TODO: store reference values for these in the texture?
8200 if (r_shadow_gloss.integer > 0)
8202 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8204 if (r_shadow_glossintensity.value > 0)
8206 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8207 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8208 specularscale = r_shadow_glossintensity.value;
8211 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8213 t->glosstexture = r_texture_white;
8214 t->backgroundglosstexture = r_texture_white;
8215 specularscale = r_shadow_gloss2intensity.value;
8216 t->specularpower = r_shadow_gloss2exponent.value;
8219 specularscale *= t->specularscalemod;
8220 t->specularpower *= t->specularpowermod;
8222 // lightmaps mode looks bad with dlights using actual texturing, so turn
8223 // off the colormap and glossmap, but leave the normalmap on as it still
8224 // accurately represents the shading involved
8225 if (gl_lightmaps.integer)
8227 t->basetexture = r_texture_grey128;
8228 t->pantstexture = r_texture_black;
8229 t->shirttexture = r_texture_black;
8230 if (gl_lightmaps.integer < 2)
8231 t->nmaptexture = r_texture_blanknormalmap;
8232 t->glosstexture = r_texture_black;
8233 t->glowtexture = NULL;
8234 t->fogtexture = NULL;
8235 t->reflectmasktexture = NULL;
8236 t->backgroundbasetexture = NULL;
8237 if (gl_lightmaps.integer < 2)
8238 t->backgroundnmaptexture = r_texture_blanknormalmap;
8239 t->backgroundglosstexture = r_texture_black;
8240 t->backgroundglowtexture = NULL;
8242 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8245 if (specularscale != 1.0f)
8247 for (q = 0; q < 3; q++)
8249 t->render_modellight_specular[q] *= specularscale;
8250 t->render_lightmap_specular[q] *= specularscale;
8251 t->render_rtlight_specular[q] *= specularscale;
8255 t->currentnumlayers = 0;
8256 if (t->currentmaterialflags & MATERIALFLAG_WALL)
8258 int blendfunc1, blendfunc2;
8260 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8262 blendfunc1 = GL_SRC_ALPHA;
8263 blendfunc2 = GL_ONE;
8265 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8267 blendfunc1 = GL_SRC_ALPHA;
8268 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8270 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8272 blendfunc1 = t->customblendfunc[0];
8273 blendfunc2 = t->customblendfunc[1];
8277 blendfunc1 = GL_ONE;
8278 blendfunc2 = GL_ZERO;
8280 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8281 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
8283 // basic lit geometry
8284 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, 2, 2, 2, t->currentalpha);
8285 // add pants/shirt if needed
8286 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8287 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, 2 * t->render_colormap_pants[0], 2 * t->render_colormap_pants[1], 2 * t->render_colormap_pants[2], t->currentalpha);
8288 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8289 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, 2 * t->render_colormap_shirt[0], 2 * t->render_colormap_shirt[1], 2 * t->render_colormap_shirt[2], t->currentalpha);
8293 // basic lit geometry
8294 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_diffuse[0], t->render_lightmap_diffuse[1], t->render_lightmap_diffuse[2], t->currentalpha);
8295 // add pants/shirt if needed
8296 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8297 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_diffuse[0], t->render_colormap_pants[1] * t->render_lightmap_diffuse[1], t->render_colormap_pants[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8298 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8299 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_diffuse[0], t->render_colormap_shirt[1] * t->render_lightmap_diffuse[1], t->render_colormap_shirt[2] * t->render_lightmap_diffuse[2], t->currentalpha);
8300 // now add ambient passes if needed
8301 if (VectorLength2(t->render_lightmap_ambient) >= (1.0f/1048576.0f))
8303 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->render_lightmap_ambient[0], t->render_lightmap_ambient[1], t->render_lightmap_ambient[2], t->currentalpha);
8304 if (VectorLength2(t->render_colormap_pants) >= (1.0f / 1048576.0f) && t->pantstexture)
8305 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, t->render_colormap_pants[0] * t->render_lightmap_ambient[0], t->render_colormap_pants[1] * t->render_lightmap_ambient[1], t->render_colormap_pants[2] * t->render_lightmap_ambient[2], t->currentalpha);
8306 if (VectorLength2(t->render_colormap_shirt) >= (1.0f / 1048576.0f) && t->shirttexture)
8307 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, t->render_colormap_shirt[0] * t->render_lightmap_ambient[0], t->render_colormap_shirt[1] * t->render_lightmap_ambient[1], t->render_colormap_shirt[2] * t->render_lightmap_ambient[2], t->currentalpha);
8310 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8311 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, t->render_glowmod[0], t->render_glowmod[1], t->render_glowmod[2], t->currentalpha);
8312 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8314 // if this is opaque use alpha blend which will darken the earlier
8317 // if this is an alpha blended material, all the earlier passes
8318 // were darkened by fog already, so we only need to add the fog
8319 // color ontop through the fog mask texture
8321 // if this is an additive blended material, all the earlier passes
8322 // were darkened by fog already, and we should not add fog color
8323 // (because the background was not darkened, there is no fog color
8324 // that was lost behind it).
8325 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->currentalpha);
8332 rsurfacestate_t rsurface;
8334 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8336 dp_model_t *model = ent->model;
8337 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8339 rsurface.entity = (entity_render_t *)ent;
8340 rsurface.skeleton = ent->skeleton;
8341 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8342 rsurface.ent_skinnum = ent->skinnum;
8343 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;
8344 rsurface.ent_flags = ent->flags;
8345 if (r_fullbright_directed.integer && (r_fullbright.integer || !model->lit))
8346 rsurface.ent_flags |= RENDER_LIGHT | RENDER_DYNAMICMODELLIGHT;
8347 rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8348 rsurface.matrix = ent->matrix;
8349 rsurface.inversematrix = ent->inversematrix;
8350 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8351 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8352 R_EntityMatrix(&rsurface.matrix);
8353 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8354 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8355 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist * rsurface.inversematrixscale;
8356 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8357 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8358 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8359 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8360 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8361 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8362 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8363 if (ent->model->brush.submodel && !prepass)
8365 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8366 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8368 // if the animcache code decided it should use the shader path, skip the deform step
8369 rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8370 rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8371 rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8372 rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8373 rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8374 if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8376 if (ent->animcache_vertex3f)
8378 r_refdef.stats[r_stat_batch_entitycache_count]++;
8379 r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8380 r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8381 r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8382 rsurface.modelvertex3f = ent->animcache_vertex3f;
8383 rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8384 rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8385 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8386 rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8387 rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8388 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8389 rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8390 rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8391 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8392 rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8393 rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8394 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8395 rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8396 rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8398 else if (wanttangents)
8400 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8401 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8402 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8403 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8404 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8405 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8406 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8407 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8408 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8409 rsurface.modelvertexmesh = NULL;
8410 rsurface.modelvertexmesh_vertexbuffer = NULL;
8411 rsurface.modelvertexmesh_bufferoffset = 0;
8412 rsurface.modelvertex3f_vertexbuffer = NULL;
8413 rsurface.modelvertex3f_bufferoffset = 0;
8414 rsurface.modelvertex3f_vertexbuffer = 0;
8415 rsurface.modelvertex3f_bufferoffset = 0;
8416 rsurface.modelsvector3f_vertexbuffer = 0;
8417 rsurface.modelsvector3f_bufferoffset = 0;
8418 rsurface.modeltvector3f_vertexbuffer = 0;
8419 rsurface.modeltvector3f_bufferoffset = 0;
8420 rsurface.modelnormal3f_vertexbuffer = 0;
8421 rsurface.modelnormal3f_bufferoffset = 0;
8423 else if (wantnormals)
8425 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8426 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8427 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8428 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8429 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8430 rsurface.modelsvector3f = NULL;
8431 rsurface.modeltvector3f = NULL;
8432 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8433 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8434 rsurface.modelvertexmesh = NULL;
8435 rsurface.modelvertexmesh_vertexbuffer = NULL;
8436 rsurface.modelvertexmesh_bufferoffset = 0;
8437 rsurface.modelvertex3f_vertexbuffer = NULL;
8438 rsurface.modelvertex3f_bufferoffset = 0;
8439 rsurface.modelvertex3f_vertexbuffer = 0;
8440 rsurface.modelvertex3f_bufferoffset = 0;
8441 rsurface.modelsvector3f_vertexbuffer = 0;
8442 rsurface.modelsvector3f_bufferoffset = 0;
8443 rsurface.modeltvector3f_vertexbuffer = 0;
8444 rsurface.modeltvector3f_bufferoffset = 0;
8445 rsurface.modelnormal3f_vertexbuffer = 0;
8446 rsurface.modelnormal3f_bufferoffset = 0;
8450 r_refdef.stats[r_stat_batch_entityanimate_count]++;
8451 r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8452 r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8453 r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8454 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8455 rsurface.modelsvector3f = NULL;
8456 rsurface.modeltvector3f = NULL;
8457 rsurface.modelnormal3f = NULL;
8458 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8459 rsurface.modelvertexmesh = NULL;
8460 rsurface.modelvertexmesh_vertexbuffer = NULL;
8461 rsurface.modelvertexmesh_bufferoffset = 0;
8462 rsurface.modelvertex3f_vertexbuffer = NULL;
8463 rsurface.modelvertex3f_bufferoffset = 0;
8464 rsurface.modelvertex3f_vertexbuffer = 0;
8465 rsurface.modelvertex3f_bufferoffset = 0;
8466 rsurface.modelsvector3f_vertexbuffer = 0;
8467 rsurface.modelsvector3f_bufferoffset = 0;
8468 rsurface.modeltvector3f_vertexbuffer = 0;
8469 rsurface.modeltvector3f_bufferoffset = 0;
8470 rsurface.modelnormal3f_vertexbuffer = 0;
8471 rsurface.modelnormal3f_bufferoffset = 0;
8473 rsurface.modelgeneratedvertex = true;
8477 if (rsurface.entityskeletaltransform3x4)
8479 r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8480 r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8481 r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8482 r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8486 r_refdef.stats[r_stat_batch_entitystatic_count]++;
8487 r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8488 r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8489 r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8491 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
8492 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8493 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8494 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8495 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8496 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8497 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8498 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8499 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8500 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
8501 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8502 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8503 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8504 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8505 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8506 rsurface.modelgeneratedvertex = false;
8508 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
8509 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8510 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8511 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
8512 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8513 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8514 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
8515 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8516 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8517 rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8518 rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519 rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8520 rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8521 rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8522 rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8523 rsurface.modelelement3i = model->surfmesh.data_element3i;
8524 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8525 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8526 rsurface.modelelement3s = model->surfmesh.data_element3s;
8527 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8528 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8529 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8530 rsurface.modelnumvertices = model->surfmesh.num_vertices;
8531 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8532 rsurface.modelsurfaces = model->data_surfaces;
8533 rsurface.batchgeneratedvertex = false;
8534 rsurface.batchfirstvertex = 0;
8535 rsurface.batchnumvertices = 0;
8536 rsurface.batchfirsttriangle = 0;
8537 rsurface.batchnumtriangles = 0;
8538 rsurface.batchvertex3f = NULL;
8539 rsurface.batchvertex3f_vertexbuffer = NULL;
8540 rsurface.batchvertex3f_bufferoffset = 0;
8541 rsurface.batchsvector3f = NULL;
8542 rsurface.batchsvector3f_vertexbuffer = NULL;
8543 rsurface.batchsvector3f_bufferoffset = 0;
8544 rsurface.batchtvector3f = NULL;
8545 rsurface.batchtvector3f_vertexbuffer = NULL;
8546 rsurface.batchtvector3f_bufferoffset = 0;
8547 rsurface.batchnormal3f = NULL;
8548 rsurface.batchnormal3f_vertexbuffer = NULL;
8549 rsurface.batchnormal3f_bufferoffset = 0;
8550 rsurface.batchlightmapcolor4f = NULL;
8551 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8552 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8553 rsurface.batchtexcoordtexture2f = NULL;
8554 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8555 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8556 rsurface.batchtexcoordlightmap2f = NULL;
8557 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8558 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8559 rsurface.batchskeletalindex4ub = NULL;
8560 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8561 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8562 rsurface.batchskeletalweight4ub = NULL;
8563 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8564 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8565 rsurface.batchvertexmesh = NULL;
8566 rsurface.batchvertexmesh_vertexbuffer = NULL;
8567 rsurface.batchvertexmesh_bufferoffset = 0;
8568 rsurface.batchelement3i = NULL;
8569 rsurface.batchelement3i_indexbuffer = NULL;
8570 rsurface.batchelement3i_bufferoffset = 0;
8571 rsurface.batchelement3s = NULL;
8572 rsurface.batchelement3s_indexbuffer = NULL;
8573 rsurface.batchelement3s_bufferoffset = 0;
8574 rsurface.passcolor4f = NULL;
8575 rsurface.passcolor4f_vertexbuffer = NULL;
8576 rsurface.passcolor4f_bufferoffset = 0;
8577 rsurface.forcecurrenttextureupdate = false;
8580 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)
8582 rsurface.entity = r_refdef.scene.worldentity;
8583 rsurface.skeleton = NULL;
8584 rsurface.ent_skinnum = 0;
8585 rsurface.ent_qwskin = -1;
8586 rsurface.ent_flags = entflags;
8587 rsurface.shadertime = r_refdef.scene.time - shadertime;
8588 rsurface.modelnumvertices = numvertices;
8589 rsurface.modelnumtriangles = numtriangles;
8590 rsurface.matrix = *matrix;
8591 rsurface.inversematrix = *inversematrix;
8592 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8593 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8594 R_EntityMatrix(&rsurface.matrix);
8595 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8596 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8597 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8598 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8599 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8600 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8601 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8602 rsurface.frameblend[0].lerp = 1;
8603 rsurface.ent_alttextures = false;
8604 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8605 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8606 rsurface.entityskeletaltransform3x4 = NULL;
8607 rsurface.entityskeletaltransform3x4buffer = NULL;
8608 rsurface.entityskeletaltransform3x4offset = 0;
8609 rsurface.entityskeletaltransform3x4size = 0;
8610 rsurface.entityskeletalnumtransforms = 0;
8611 r_refdef.stats[r_stat_batch_entitycustom_count]++;
8612 r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8613 r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8614 r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8617 rsurface.modelvertex3f = (float *)vertex3f;
8618 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8619 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8620 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8622 else if (wantnormals)
8624 rsurface.modelvertex3f = (float *)vertex3f;
8625 rsurface.modelsvector3f = NULL;
8626 rsurface.modeltvector3f = NULL;
8627 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8631 rsurface.modelvertex3f = (float *)vertex3f;
8632 rsurface.modelsvector3f = NULL;
8633 rsurface.modeltvector3f = NULL;
8634 rsurface.modelnormal3f = NULL;
8636 rsurface.modelvertexmesh = NULL;
8637 rsurface.modelvertexmesh_vertexbuffer = NULL;
8638 rsurface.modelvertexmesh_bufferoffset = 0;
8639 rsurface.modelvertex3f_vertexbuffer = 0;
8640 rsurface.modelvertex3f_bufferoffset = 0;
8641 rsurface.modelsvector3f_vertexbuffer = 0;
8642 rsurface.modelsvector3f_bufferoffset = 0;
8643 rsurface.modeltvector3f_vertexbuffer = 0;
8644 rsurface.modeltvector3f_bufferoffset = 0;
8645 rsurface.modelnormal3f_vertexbuffer = 0;
8646 rsurface.modelnormal3f_bufferoffset = 0;
8647 rsurface.modelgeneratedvertex = true;
8648 rsurface.modellightmapcolor4f = (float *)color4f;
8649 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8650 rsurface.modellightmapcolor4f_bufferoffset = 0;
8651 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8652 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8653 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8654 rsurface.modeltexcoordlightmap2f = NULL;
8655 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8656 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8657 rsurface.modelskeletalindex4ub = NULL;
8658 rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8659 rsurface.modelskeletalindex4ub_bufferoffset = 0;
8660 rsurface.modelskeletalweight4ub = NULL;
8661 rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8662 rsurface.modelskeletalweight4ub_bufferoffset = 0;
8663 rsurface.modelelement3i = (int *)element3i;
8664 rsurface.modelelement3i_indexbuffer = NULL;
8665 rsurface.modelelement3i_bufferoffset = 0;
8666 rsurface.modelelement3s = (unsigned short *)element3s;
8667 rsurface.modelelement3s_indexbuffer = NULL;
8668 rsurface.modelelement3s_bufferoffset = 0;
8669 rsurface.modellightmapoffsets = NULL;
8670 rsurface.modelsurfaces = NULL;
8671 rsurface.batchgeneratedvertex = false;
8672 rsurface.batchfirstvertex = 0;
8673 rsurface.batchnumvertices = 0;
8674 rsurface.batchfirsttriangle = 0;
8675 rsurface.batchnumtriangles = 0;
8676 rsurface.batchvertex3f = NULL;
8677 rsurface.batchvertex3f_vertexbuffer = NULL;
8678 rsurface.batchvertex3f_bufferoffset = 0;
8679 rsurface.batchsvector3f = NULL;
8680 rsurface.batchsvector3f_vertexbuffer = NULL;
8681 rsurface.batchsvector3f_bufferoffset = 0;
8682 rsurface.batchtvector3f = NULL;
8683 rsurface.batchtvector3f_vertexbuffer = NULL;
8684 rsurface.batchtvector3f_bufferoffset = 0;
8685 rsurface.batchnormal3f = NULL;
8686 rsurface.batchnormal3f_vertexbuffer = NULL;
8687 rsurface.batchnormal3f_bufferoffset = 0;
8688 rsurface.batchlightmapcolor4f = NULL;
8689 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8690 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8691 rsurface.batchtexcoordtexture2f = NULL;
8692 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8693 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8694 rsurface.batchtexcoordlightmap2f = NULL;
8695 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8696 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8697 rsurface.batchskeletalindex4ub = NULL;
8698 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8699 rsurface.batchskeletalindex4ub_bufferoffset = 0;
8700 rsurface.batchskeletalweight4ub = NULL;
8701 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8702 rsurface.batchskeletalweight4ub_bufferoffset = 0;
8703 rsurface.batchvertexmesh = NULL;
8704 rsurface.batchvertexmesh_vertexbuffer = NULL;
8705 rsurface.batchvertexmesh_bufferoffset = 0;
8706 rsurface.batchelement3i = NULL;
8707 rsurface.batchelement3i_indexbuffer = NULL;
8708 rsurface.batchelement3i_bufferoffset = 0;
8709 rsurface.batchelement3s = NULL;
8710 rsurface.batchelement3s_indexbuffer = NULL;
8711 rsurface.batchelement3s_bufferoffset = 0;
8712 rsurface.passcolor4f = NULL;
8713 rsurface.passcolor4f_vertexbuffer = NULL;
8714 rsurface.passcolor4f_bufferoffset = 0;
8715 rsurface.forcecurrenttextureupdate = true;
8717 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8719 if ((wantnormals || wanttangents) && !normal3f)
8721 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8722 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8724 if (wanttangents && !svector3f)
8726 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8727 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8728 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8733 float RSurf_FogPoint(const float *v)
8735 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8736 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8737 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8738 float FogHeightFade = r_refdef.fogheightfade;
8740 unsigned int fogmasktableindex;
8741 if (r_refdef.fogplaneviewabove)
8742 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8744 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8745 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8746 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8749 float RSurf_FogVertex(const float *v)
8751 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8752 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8753 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8754 float FogHeightFade = rsurface.fogheightfade;
8756 unsigned int fogmasktableindex;
8757 if (r_refdef.fogplaneviewabove)
8758 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8760 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8761 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8762 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8765 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8768 for (i = 0;i < numelements;i++)
8769 outelement3i[i] = inelement3i[i] + adjust;
8772 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8773 extern cvar_t gl_vbo;
8774 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8782 int surfacefirsttriangle;
8783 int surfacenumtriangles;
8784 int surfacefirstvertex;
8785 int surfaceendvertex;
8786 int surfacenumvertices;
8787 int batchnumsurfaces = texturenumsurfaces;
8788 int batchnumvertices;
8789 int batchnumtriangles;
8793 qboolean dynamicvertex;
8796 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8799 q3shaderinfo_deform_t *deform;
8800 const msurface_t *surface, *firstsurface;
8801 r_vertexmesh_t *vertexmesh;
8802 if (!texturenumsurfaces)
8804 // find vertex range of this surface batch
8806 firstsurface = texturesurfacelist[0];
8807 firsttriangle = firstsurface->num_firsttriangle;
8808 batchnumvertices = 0;
8809 batchnumtriangles = 0;
8810 firstvertex = endvertex = firstsurface->num_firstvertex;
8811 for (i = 0;i < texturenumsurfaces;i++)
8813 surface = texturesurfacelist[i];
8814 if (surface != firstsurface + i)
8816 surfacefirstvertex = surface->num_firstvertex;
8817 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8818 surfacenumvertices = surface->num_vertices;
8819 surfacenumtriangles = surface->num_triangles;
8820 if (firstvertex > surfacefirstvertex)
8821 firstvertex = surfacefirstvertex;
8822 if (endvertex < surfaceendvertex)
8823 endvertex = surfaceendvertex;
8824 batchnumvertices += surfacenumvertices;
8825 batchnumtriangles += surfacenumtriangles;
8828 r_refdef.stats[r_stat_batch_batches]++;
8830 r_refdef.stats[r_stat_batch_withgaps]++;
8831 r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
8832 r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
8833 r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
8835 // we now know the vertex range used, and if there are any gaps in it
8836 rsurface.batchfirstvertex = firstvertex;
8837 rsurface.batchnumvertices = endvertex - firstvertex;
8838 rsurface.batchfirsttriangle = firsttriangle;
8839 rsurface.batchnumtriangles = batchnumtriangles;
8841 // this variable holds flags for which properties have been updated that
8842 // may require regenerating vertexmesh array...
8845 // check if any dynamic vertex processing must occur
8846 dynamicvertex = false;
8848 // a cvar to force the dynamic vertex path to be taken, for debugging
8849 if (r_batch_debugdynamicvertexpath.integer)
8853 r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
8854 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
8855 r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
8856 r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
8858 dynamicvertex = true;
8861 // if there is a chance of animated vertex colors, it's a dynamic batch
8862 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8866 r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
8867 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
8868 r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
8869 r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
8871 dynamicvertex = true;
8872 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8875 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8877 switch (deform->deform)
8880 case Q3DEFORM_PROJECTIONSHADOW:
8881 case Q3DEFORM_TEXT0:
8882 case Q3DEFORM_TEXT1:
8883 case Q3DEFORM_TEXT2:
8884 case Q3DEFORM_TEXT3:
8885 case Q3DEFORM_TEXT4:
8886 case Q3DEFORM_TEXT5:
8887 case Q3DEFORM_TEXT6:
8888 case Q3DEFORM_TEXT7:
8891 case Q3DEFORM_AUTOSPRITE:
8894 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
8895 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
8896 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
8897 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
8899 dynamicvertex = true;
8900 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8901 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8903 case Q3DEFORM_AUTOSPRITE2:
8906 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
8907 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
8908 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
8909 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
8911 dynamicvertex = true;
8912 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8913 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8915 case Q3DEFORM_NORMAL:
8918 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
8919 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
8920 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
8921 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
8923 dynamicvertex = true;
8924 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8925 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8928 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8929 break; // if wavefunc is a nop, ignore this transform
8932 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
8933 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
8934 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
8935 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
8937 dynamicvertex = true;
8938 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8939 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8941 case Q3DEFORM_BULGE:
8944 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
8945 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
8946 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
8947 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
8949 dynamicvertex = true;
8950 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8951 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8954 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8955 break; // if wavefunc is a nop, ignore this transform
8958 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
8959 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
8960 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
8961 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
8963 dynamicvertex = true;
8964 batchneed |= BATCHNEED_ARRAY_VERTEX;
8965 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8969 if (rsurface.texture->materialshaderpass)
8971 switch (rsurface.texture->materialshaderpass->tcgen.tcgen)
8974 case Q3TCGEN_TEXTURE:
8976 case Q3TCGEN_LIGHTMAP:
8979 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
8980 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
8981 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
8982 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
8984 dynamicvertex = true;
8985 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8986 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8988 case Q3TCGEN_VECTOR:
8991 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
8992 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
8993 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
8994 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
8996 dynamicvertex = true;
8997 batchneed |= BATCHNEED_ARRAY_VERTEX;
8998 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9000 case Q3TCGEN_ENVIRONMENT:
9003 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9004 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9005 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9006 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9008 dynamicvertex = true;
9009 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9010 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9013 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9017 r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9018 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9019 r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9020 r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9022 dynamicvertex = true;
9023 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9024 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9028 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9032 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9033 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9034 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9035 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9037 dynamicvertex = true;
9038 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9041 // when the model data has no vertex buffer (dynamic mesh), we need to
9043 if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9044 batchneed |= BATCHNEED_NOGAPS;
9046 // the caller can specify BATCHNEED_NOGAPS to force a batch with
9047 // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9048 // we ensure this by treating the vertex batch as dynamic...
9049 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9053 r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9054 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9055 r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9056 r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9058 dynamicvertex = true;
9063 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9064 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
9065 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
9066 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
9067 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9068 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9069 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9070 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL) batchneed |= BATCHNEED_ARRAY_SKELETAL;
9073 // if needsupdate, we have to do a dynamic vertex batch for sure
9074 if (needsupdate & batchneed)
9078 r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9079 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9080 r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9081 r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9083 dynamicvertex = true;
9086 // see if we need to build vertexmesh from arrays
9087 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9091 r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9092 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9093 r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9094 r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9096 dynamicvertex = true;
9099 // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9100 if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9101 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9103 rsurface.batchvertex3f = rsurface.modelvertex3f;
9104 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9105 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9106 rsurface.batchsvector3f = rsurface.modelsvector3f;
9107 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9108 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9109 rsurface.batchtvector3f = rsurface.modeltvector3f;
9110 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9111 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9112 rsurface.batchnormal3f = rsurface.modelnormal3f;
9113 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9114 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9115 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9116 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
9117 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
9118 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9119 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
9120 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
9121 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9122 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9123 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9124 rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9125 rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9126 rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9127 rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9128 rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9129 rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9130 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9131 rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9132 rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9133 rsurface.batchelement3i = rsurface.modelelement3i;
9134 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9135 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9136 rsurface.batchelement3s = rsurface.modelelement3s;
9137 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9138 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9139 rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9140 rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9141 rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9142 rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9143 rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9145 // if any dynamic vertex processing has to occur in software, we copy the
9146 // entire surface list together before processing to rebase the vertices
9147 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9149 // if any gaps exist and we do not have a static vertex buffer, we have to
9150 // copy the surface list together to avoid wasting upload bandwidth on the
9151 // vertices in the gaps.
9153 // if gaps exist and we have a static vertex buffer, we can choose whether
9154 // to combine the index buffer ranges into one dynamic index buffer or
9155 // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9157 // in many cases the batch is reduced to one draw call.
9159 rsurface.batchmultidraw = false;
9160 rsurface.batchmultidrawnumsurfaces = 0;
9161 rsurface.batchmultidrawsurfacelist = NULL;
9165 // static vertex data, just set pointers...
9166 rsurface.batchgeneratedvertex = false;
9167 // if there are gaps, we want to build a combined index buffer,
9168 // otherwise use the original static buffer with an appropriate offset
9171 r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9172 r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9173 r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9174 r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9175 if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9177 rsurface.batchmultidraw = true;
9178 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9179 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9182 // build a new triangle elements array for this batch
9183 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9184 rsurface.batchfirsttriangle = 0;
9186 for (i = 0;i < texturenumsurfaces;i++)
9188 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9189 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9190 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9191 numtriangles += surfacenumtriangles;
9193 rsurface.batchelement3i_indexbuffer = NULL;
9194 rsurface.batchelement3i_bufferoffset = 0;
9195 rsurface.batchelement3s = NULL;
9196 rsurface.batchelement3s_indexbuffer = NULL;
9197 rsurface.batchelement3s_bufferoffset = 0;
9198 if (endvertex <= 65536)
9200 // make a 16bit (unsigned short) index array if possible
9201 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9202 for (i = 0;i < numtriangles*3;i++)
9203 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9205 // upload buffer data for the copytriangles batch
9206 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9208 if (rsurface.batchelement3s)
9209 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9210 else if (rsurface.batchelement3i)
9211 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9216 r_refdef.stats[r_stat_batch_fast_batches] += 1;
9217 r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9218 r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9219 r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9224 // something needs software processing, do it for real...
9225 // we only directly handle separate array data in this case and then
9226 // generate interleaved data if needed...
9227 rsurface.batchgeneratedvertex = true;
9228 r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9229 r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9230 r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9231 r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9233 // now copy the vertex data into a combined array and make an index array
9234 // (this is what Quake3 does all the time)
9235 // we also apply any skeletal animation here that would have been done in
9236 // the vertex shader, because most of the dynamic vertex animation cases
9237 // need actual vertex positions and normals
9238 //if (dynamicvertex)
9240 rsurface.batchvertexmesh = NULL;
9241 rsurface.batchvertexmesh_vertexbuffer = NULL;
9242 rsurface.batchvertexmesh_bufferoffset = 0;
9243 rsurface.batchvertex3f = NULL;
9244 rsurface.batchvertex3f_vertexbuffer = NULL;
9245 rsurface.batchvertex3f_bufferoffset = 0;
9246 rsurface.batchsvector3f = NULL;
9247 rsurface.batchsvector3f_vertexbuffer = NULL;
9248 rsurface.batchsvector3f_bufferoffset = 0;
9249 rsurface.batchtvector3f = NULL;
9250 rsurface.batchtvector3f_vertexbuffer = NULL;
9251 rsurface.batchtvector3f_bufferoffset = 0;
9252 rsurface.batchnormal3f = NULL;
9253 rsurface.batchnormal3f_vertexbuffer = NULL;
9254 rsurface.batchnormal3f_bufferoffset = 0;
9255 rsurface.batchlightmapcolor4f = NULL;
9256 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9257 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9258 rsurface.batchtexcoordtexture2f = NULL;
9259 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9260 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9261 rsurface.batchtexcoordlightmap2f = NULL;
9262 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9263 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9264 rsurface.batchskeletalindex4ub = NULL;
9265 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9266 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9267 rsurface.batchskeletalweight4ub = NULL;
9268 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9269 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9270 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9271 rsurface.batchelement3i_indexbuffer = NULL;
9272 rsurface.batchelement3i_bufferoffset = 0;
9273 rsurface.batchelement3s = NULL;
9274 rsurface.batchelement3s_indexbuffer = NULL;
9275 rsurface.batchelement3s_bufferoffset = 0;
9276 rsurface.batchskeletaltransform3x4buffer = NULL;
9277 rsurface.batchskeletaltransform3x4offset = 0;
9278 rsurface.batchskeletaltransform3x4size = 0;
9279 // we'll only be setting up certain arrays as needed
9280 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9281 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9282 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9283 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9284 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9285 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9286 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9288 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9289 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9291 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9292 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9293 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9294 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9295 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9296 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9297 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9299 rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9300 rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9304 for (i = 0;i < texturenumsurfaces;i++)
9306 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9307 surfacenumvertices = texturesurfacelist[i]->num_vertices;
9308 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9309 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9310 // copy only the data requested
9311 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9312 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9313 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9315 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9317 if (rsurface.batchvertex3f)
9318 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9320 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9322 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9324 if (rsurface.modelnormal3f)
9325 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9327 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9329 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9331 if (rsurface.modelsvector3f)
9333 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9334 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9338 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9339 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9342 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9344 if (rsurface.modellightmapcolor4f)
9345 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9347 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9349 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9351 if (rsurface.modeltexcoordtexture2f)
9352 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9354 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9356 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9358 if (rsurface.modeltexcoordlightmap2f)
9359 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9361 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9363 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9365 if (rsurface.modelskeletalindex4ub)
9367 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9368 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9372 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9373 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9374 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9375 for (j = 0;j < surfacenumvertices;j++)
9380 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9381 numvertices += surfacenumvertices;
9382 numtriangles += surfacenumtriangles;
9385 // generate a 16bit index array as well if possible
9386 // (in general, dynamic batches fit)
9387 if (numvertices <= 65536)
9389 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9390 for (i = 0;i < numtriangles*3;i++)
9391 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9394 // since we've copied everything, the batch now starts at 0
9395 rsurface.batchfirstvertex = 0;
9396 rsurface.batchnumvertices = batchnumvertices;
9397 rsurface.batchfirsttriangle = 0;
9398 rsurface.batchnumtriangles = batchnumtriangles;
9401 // apply skeletal animation that would have been done in the vertex shader
9402 if (rsurface.batchskeletaltransform3x4)
9404 const unsigned char *si;
9405 const unsigned char *sw;
9407 const float *b = rsurface.batchskeletaltransform3x4;
9408 float *vp, *vs, *vt, *vn;
9410 float m[3][4], n[3][4];
9411 float tp[3], ts[3], tt[3], tn[3];
9412 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9413 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9414 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9415 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9416 si = rsurface.batchskeletalindex4ub;
9417 sw = rsurface.batchskeletalweight4ub;
9418 vp = rsurface.batchvertex3f;
9419 vs = rsurface.batchsvector3f;
9420 vt = rsurface.batchtvector3f;
9421 vn = rsurface.batchnormal3f;
9422 memset(m[0], 0, sizeof(m));
9423 memset(n[0], 0, sizeof(n));
9424 for (i = 0;i < batchnumvertices;i++)
9426 t[0] = b + si[0]*12;
9429 // common case - only one matrix
9443 else if (sw[2] + sw[3])
9446 t[1] = b + si[1]*12;
9447 t[2] = b + si[2]*12;
9448 t[3] = b + si[3]*12;
9449 w[0] = sw[0] * (1.0f / 255.0f);
9450 w[1] = sw[1] * (1.0f / 255.0f);
9451 w[2] = sw[2] * (1.0f / 255.0f);
9452 w[3] = sw[3] * (1.0f / 255.0f);
9453 // blend the matrices
9454 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9455 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9456 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9457 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9458 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9459 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9460 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9461 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9462 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9463 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9464 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9465 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9470 t[1] = b + si[1]*12;
9471 w[0] = sw[0] * (1.0f / 255.0f);
9472 w[1] = sw[1] * (1.0f / 255.0f);
9473 // blend the matrices
9474 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9475 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9476 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9477 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9478 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9479 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9480 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9481 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9482 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9483 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9484 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9485 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9489 // modify the vertex
9491 vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9492 vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9493 vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9497 // the normal transformation matrix is a set of cross products...
9498 CrossProduct(m[1], m[2], n[0]);
9499 CrossProduct(m[2], m[0], n[1]);
9500 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9502 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9503 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9504 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9505 VectorNormalize(vn);
9510 vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9511 vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9512 vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9513 VectorNormalize(vs);
9516 vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9517 vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9518 vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9519 VectorNormalize(vt);
9524 rsurface.batchskeletaltransform3x4 = NULL;
9525 rsurface.batchskeletalnumtransforms = 0;
9528 // q1bsp surfaces rendered in vertex color mode have to have colors
9529 // calculated based on lightstyles
9530 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9532 // generate color arrays for the surfaces in this list
9537 const unsigned char *lm;
9538 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9539 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9540 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9542 for (i = 0;i < texturenumsurfaces;i++)
9544 surface = texturesurfacelist[i];
9545 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9546 surfacenumvertices = surface->num_vertices;
9547 if (surface->lightmapinfo->samples)
9549 for (j = 0;j < surfacenumvertices;j++)
9551 lm = surface->lightmapinfo->samples + offsets[j];
9552 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9553 VectorScale(lm, scale, c);
9554 if (surface->lightmapinfo->styles[1] != 255)
9556 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9558 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9559 VectorMA(c, scale, lm, c);
9560 if (surface->lightmapinfo->styles[2] != 255)
9563 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9564 VectorMA(c, scale, lm, c);
9565 if (surface->lightmapinfo->styles[3] != 255)
9568 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9569 VectorMA(c, scale, lm, c);
9576 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);
9582 for (j = 0;j < surfacenumvertices;j++)
9584 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9591 // if vertices are deformed (sprite flares and things in maps, possibly
9592 // water waves, bulges and other deformations), modify the copied vertices
9594 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9597 switch (deform->deform)
9600 case Q3DEFORM_PROJECTIONSHADOW:
9601 case Q3DEFORM_TEXT0:
9602 case Q3DEFORM_TEXT1:
9603 case Q3DEFORM_TEXT2:
9604 case Q3DEFORM_TEXT3:
9605 case Q3DEFORM_TEXT4:
9606 case Q3DEFORM_TEXT5:
9607 case Q3DEFORM_TEXT6:
9608 case Q3DEFORM_TEXT7:
9611 case Q3DEFORM_AUTOSPRITE:
9612 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9613 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9614 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9615 VectorNormalize(newforward);
9616 VectorNormalize(newright);
9617 VectorNormalize(newup);
9618 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9619 // rsurface.batchvertex3f_vertexbuffer = NULL;
9620 // rsurface.batchvertex3f_bufferoffset = 0;
9621 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9622 // rsurface.batchsvector3f_vertexbuffer = NULL;
9623 // rsurface.batchsvector3f_bufferoffset = 0;
9624 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9625 // rsurface.batchtvector3f_vertexbuffer = NULL;
9626 // rsurface.batchtvector3f_bufferoffset = 0;
9627 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9628 // rsurface.batchnormal3f_vertexbuffer = NULL;
9629 // rsurface.batchnormal3f_bufferoffset = 0;
9630 // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9631 if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9632 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9633 if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9634 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);
9635 // a single autosprite surface can contain multiple sprites...
9636 for (j = 0;j < batchnumvertices - 3;j += 4)
9638 VectorClear(center);
9639 for (i = 0;i < 4;i++)
9640 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9641 VectorScale(center, 0.25f, center);
9642 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9643 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9644 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9645 for (i = 0;i < 4;i++)
9647 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9648 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9651 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9652 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9653 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);
9655 case Q3DEFORM_AUTOSPRITE2:
9656 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9657 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9658 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9659 VectorNormalize(newforward);
9660 VectorNormalize(newright);
9661 VectorNormalize(newup);
9662 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9663 // rsurface.batchvertex3f_vertexbuffer = NULL;
9664 // rsurface.batchvertex3f_bufferoffset = 0;
9666 const float *v1, *v2;
9676 memset(shortest, 0, sizeof(shortest));
9677 // a single autosprite surface can contain multiple sprites...
9678 for (j = 0;j < batchnumvertices - 3;j += 4)
9680 VectorClear(center);
9681 for (i = 0;i < 4;i++)
9682 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9683 VectorScale(center, 0.25f, center);
9684 // find the two shortest edges, then use them to define the
9685 // axis vectors for rotating around the central axis
9686 for (i = 0;i < 6;i++)
9688 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9689 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9690 l = VectorDistance2(v1, v2);
9691 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9693 l += (1.0f / 1024.0f);
9694 if (shortest[0].length2 > l || i == 0)
9696 shortest[1] = shortest[0];
9697 shortest[0].length2 = l;
9698 shortest[0].v1 = v1;
9699 shortest[0].v2 = v2;
9701 else if (shortest[1].length2 > l || i == 1)
9703 shortest[1].length2 = l;
9704 shortest[1].v1 = v1;
9705 shortest[1].v2 = v2;
9708 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9709 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9710 // this calculates the right vector from the shortest edge
9711 // and the up vector from the edge midpoints
9712 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9713 VectorNormalize(right);
9714 VectorSubtract(end, start, up);
9715 VectorNormalize(up);
9716 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9717 VectorSubtract(rsurface.localvieworigin, center, forward);
9718 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9719 VectorNegate(forward, forward);
9720 VectorReflect(forward, 0, up, forward);
9721 VectorNormalize(forward);
9722 CrossProduct(up, forward, newright);
9723 VectorNormalize(newright);
9724 // rotate the quad around the up axis vector, this is made
9725 // especially easy by the fact we know the quad is flat,
9726 // so we only have to subtract the center position and
9727 // measure distance along the right vector, and then
9728 // multiply that by the newright vector and add back the
9730 // we also need to subtract the old position to undo the
9731 // displacement from the center, which we do with a
9732 // DotProduct, the subtraction/addition of center is also
9733 // optimized into DotProducts here
9734 l = DotProduct(right, center);
9735 for (i = 0;i < 4;i++)
9737 v1 = rsurface.batchvertex3f + 3*(j+i);
9738 f = DotProduct(right, v1) - l;
9739 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9743 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9745 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9746 // rsurface.batchnormal3f_vertexbuffer = NULL;
9747 // rsurface.batchnormal3f_bufferoffset = 0;
9748 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9750 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9752 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9753 // rsurface.batchsvector3f_vertexbuffer = NULL;
9754 // rsurface.batchsvector3f_bufferoffset = 0;
9755 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9756 // rsurface.batchtvector3f_vertexbuffer = NULL;
9757 // rsurface.batchtvector3f_bufferoffset = 0;
9758 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);
9761 case Q3DEFORM_NORMAL:
9762 // deform the normals to make reflections wavey
9763 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9764 rsurface.batchnormal3f_vertexbuffer = NULL;
9765 rsurface.batchnormal3f_bufferoffset = 0;
9766 for (j = 0;j < batchnumvertices;j++)
9769 float *normal = rsurface.batchnormal3f + 3*j;
9770 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9771 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9772 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9773 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9774 VectorNormalize(normal);
9776 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9778 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9779 // rsurface.batchsvector3f_vertexbuffer = NULL;
9780 // rsurface.batchsvector3f_bufferoffset = 0;
9781 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9782 // rsurface.batchtvector3f_vertexbuffer = NULL;
9783 // rsurface.batchtvector3f_bufferoffset = 0;
9784 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9788 // deform vertex array to make wavey water and flags and such
9789 waveparms[0] = deform->waveparms[0];
9790 waveparms[1] = deform->waveparms[1];
9791 waveparms[2] = deform->waveparms[2];
9792 waveparms[3] = deform->waveparms[3];
9793 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9794 break; // if wavefunc is a nop, don't make a dynamic vertex array
9795 // this is how a divisor of vertex influence on deformation
9796 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9797 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9798 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9799 // rsurface.batchvertex3f_vertexbuffer = NULL;
9800 // rsurface.batchvertex3f_bufferoffset = 0;
9801 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9802 // rsurface.batchnormal3f_vertexbuffer = NULL;
9803 // rsurface.batchnormal3f_bufferoffset = 0;
9804 for (j = 0;j < batchnumvertices;j++)
9806 // if the wavefunc depends on time, evaluate it per-vertex
9809 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9810 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9812 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9814 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9815 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9816 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9818 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9819 // rsurface.batchsvector3f_vertexbuffer = NULL;
9820 // rsurface.batchsvector3f_bufferoffset = 0;
9821 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9822 // rsurface.batchtvector3f_vertexbuffer = NULL;
9823 // rsurface.batchtvector3f_bufferoffset = 0;
9824 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9827 case Q3DEFORM_BULGE:
9828 // deform vertex array to make the surface have moving bulges
9829 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9830 // rsurface.batchvertex3f_vertexbuffer = NULL;
9831 // rsurface.batchvertex3f_bufferoffset = 0;
9832 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9833 // rsurface.batchnormal3f_vertexbuffer = NULL;
9834 // rsurface.batchnormal3f_bufferoffset = 0;
9835 for (j = 0;j < batchnumvertices;j++)
9837 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9838 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9840 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9841 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9842 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9844 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9845 // rsurface.batchsvector3f_vertexbuffer = NULL;
9846 // rsurface.batchsvector3f_bufferoffset = 0;
9847 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9848 // rsurface.batchtvector3f_vertexbuffer = NULL;
9849 // rsurface.batchtvector3f_bufferoffset = 0;
9850 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);
9854 // deform vertex array
9855 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9856 break; // if wavefunc is a nop, don't make a dynamic vertex array
9857 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9858 VectorScale(deform->parms, scale, waveparms);
9859 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9860 // rsurface.batchvertex3f_vertexbuffer = NULL;
9861 // rsurface.batchvertex3f_bufferoffset = 0;
9862 for (j = 0;j < batchnumvertices;j++)
9863 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9868 if (rsurface.batchtexcoordtexture2f && rsurface.texture->materialshaderpass)
9870 // generate texcoords based on the chosen texcoord source
9871 switch(rsurface.texture->materialshaderpass->tcgen.tcgen)
9874 case Q3TCGEN_TEXTURE:
9876 case Q3TCGEN_LIGHTMAP:
9877 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9878 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9879 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9880 if (rsurface.batchtexcoordlightmap2f)
9881 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
9883 case Q3TCGEN_VECTOR:
9884 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9885 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9886 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9887 for (j = 0;j < batchnumvertices;j++)
9889 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms);
9890 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->materialshaderpass->tcgen.parms + 3);
9893 case Q3TCGEN_ENVIRONMENT:
9894 // make environment reflections using a spheremap
9895 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9896 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9897 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9898 for (j = 0;j < batchnumvertices;j++)
9900 // identical to Q3A's method, but executed in worldspace so
9901 // carried models can be shiny too
9903 float viewer[3], d, reflected[3], worldreflected[3];
9905 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9906 // VectorNormalize(viewer);
9908 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9910 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9911 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9912 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9913 // note: this is proportinal to viewer, so we can normalize later
9915 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9916 VectorNormalize(worldreflected);
9918 // note: this sphere map only uses world x and z!
9919 // so positive and negative y will LOOK THE SAME.
9920 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9921 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9925 // the only tcmod that needs software vertex processing is turbulent, so
9926 // check for it here and apply the changes if needed
9927 // and we only support that as the first one
9928 // (handling a mixture of turbulent and other tcmods would be problematic
9929 // without punting it entirely to a software path)
9930 if (rsurface.texture->materialshaderpass->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9932 amplitude = rsurface.texture->materialshaderpass->tcmods[0].parms[1];
9933 animpos = rsurface.texture->materialshaderpass->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->materialshaderpass->tcmods[0].parms[3];
9934 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9935 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9936 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9937 for (j = 0;j < batchnumvertices;j++)
9939 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);
9940 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9945 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9947 // convert the modified arrays to vertex structs
9948 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9949 // rsurface.batchvertexmesh_vertexbuffer = NULL;
9950 // rsurface.batchvertexmesh_bufferoffset = 0;
9951 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9952 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9953 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9954 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9955 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9956 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9957 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9959 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9961 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9962 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9965 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9966 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9967 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9968 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9969 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9970 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9971 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9972 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9973 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9974 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9976 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9978 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9979 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9984 // upload buffer data for the dynamic batch
9985 if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9987 if (rsurface.batchvertexmesh)
9988 rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
9991 if (rsurface.batchvertex3f)
9992 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
9993 if (rsurface.batchsvector3f)
9994 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
9995 if (rsurface.batchtvector3f)
9996 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
9997 if (rsurface.batchnormal3f)
9998 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
9999 if (rsurface.batchlightmapcolor4f)
10000 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10001 if (rsurface.batchtexcoordtexture2f)
10002 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10003 if (rsurface.batchtexcoordlightmap2f)
10004 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10005 if (rsurface.batchskeletalindex4ub)
10006 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10007 if (rsurface.batchskeletalweight4ub)
10008 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10010 if (rsurface.batchelement3s)
10011 rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10012 else if (rsurface.batchelement3i)
10013 rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10017 void RSurf_DrawBatch(void)
10019 // sometimes a zero triangle surface (usually a degenerate patch) makes it
10020 // through the pipeline, killing it earlier in the pipeline would have
10021 // per-surface overhead rather than per-batch overhead, so it's best to
10022 // reject it here, before it hits glDraw.
10023 if (rsurface.batchnumtriangles == 0)
10026 // batch debugging code
10027 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10033 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10034 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10037 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10039 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10041 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10042 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);
10049 if (rsurface.batchmultidraw)
10051 // issue multiple draws rather than copying index data
10052 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10053 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10054 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10055 for (i = 0;i < numsurfaces;)
10057 // combine consecutive surfaces as one draw
10058 for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10059 if (surfacelist[j] != surfacelist[k] + 1)
10061 firstvertex = surfacelist[i]->num_firstvertex;
10062 endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10063 firsttriangle = surfacelist[i]->num_firsttriangle;
10064 endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10065 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);
10071 // there is only one consecutive run of index data (may have been combined)
10072 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);
10076 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10078 // pick the closest matching water plane
10079 int planeindex, vertexindex, bestplaneindex = -1;
10083 r_waterstate_waterplane_t *p;
10084 qboolean prepared = false;
10086 for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10088 if(p->camera_entity != rsurface.texture->camera_entity)
10093 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10095 if(rsurface.batchnumvertices == 0)
10098 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10100 Matrix4x4_Transform(&rsurface.matrix, v, vert);
10101 d += fabs(PlaneDiff(vert, &p->plane));
10103 if (bestd > d || bestplaneindex < 0)
10106 bestplaneindex = planeindex;
10109 return bestplaneindex;
10110 // NOTE: this MAY return a totally unrelated water plane; we can ignore
10111 // this situation though, as it might be better to render single larger
10112 // batches with useless stuff (backface culled for example) than to
10113 // render multiple smaller batches
10116 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10119 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10120 rsurface.passcolor4f_vertexbuffer = 0;
10121 rsurface.passcolor4f_bufferoffset = 0;
10122 for (i = 0;i < rsurface.batchnumvertices;i++)
10123 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10126 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10133 if (rsurface.passcolor4f)
10135 // generate color arrays
10136 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10137 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10138 rsurface.passcolor4f_vertexbuffer = 0;
10139 rsurface.passcolor4f_bufferoffset = 0;
10140 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)
10142 f = RSurf_FogVertex(v);
10151 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10152 rsurface.passcolor4f_vertexbuffer = 0;
10153 rsurface.passcolor4f_bufferoffset = 0;
10154 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10156 f = RSurf_FogVertex(v);
10165 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10172 if (!rsurface.passcolor4f)
10174 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10175 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10176 rsurface.passcolor4f_vertexbuffer = 0;
10177 rsurface.passcolor4f_bufferoffset = 0;
10178 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)
10180 f = RSurf_FogVertex(v);
10181 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10182 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10183 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10188 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10193 if (!rsurface.passcolor4f)
10195 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10196 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10197 rsurface.passcolor4f_vertexbuffer = 0;
10198 rsurface.passcolor4f_bufferoffset = 0;
10199 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10208 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10213 if (!rsurface.passcolor4f)
10215 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10216 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10217 rsurface.passcolor4f_vertexbuffer = 0;
10218 rsurface.passcolor4f_bufferoffset = 0;
10219 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10221 c2[0] = c[0] + rsurface.texture->render_lightmap_ambient[0];
10222 c2[1] = c[1] + rsurface.texture->render_lightmap_ambient[1];
10223 c2[2] = c[2] + rsurface.texture->render_lightmap_ambient[2];
10228 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10231 rsurface.passcolor4f = NULL;
10232 rsurface.passcolor4f_vertexbuffer = 0;
10233 rsurface.passcolor4f_bufferoffset = 0;
10234 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10235 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10236 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10237 GL_Color(r, g, b, a);
10238 R_Mesh_TexBind(0, rsurface.lightmaptexture);
10239 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10240 R_Mesh_TexMatrix(0, NULL);
10244 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10246 // TODO: optimize applyfog && applycolor case
10247 // just apply fog if necessary, and tint the fog color array if necessary
10248 rsurface.passcolor4f = NULL;
10249 rsurface.passcolor4f_vertexbuffer = 0;
10250 rsurface.passcolor4f_bufferoffset = 0;
10251 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10252 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10253 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10254 GL_Color(r, g, b, a);
10258 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10261 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10262 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10263 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10264 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10265 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10266 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10267 GL_Color(r, g, b, a);
10271 static void RSurf_DrawBatch_GL11_ClampColor(void)
10276 if (!rsurface.passcolor4f)
10278 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10280 c2[0] = bound(0.0f, c1[0], 1.0f);
10281 c2[1] = bound(0.0f, c1[1], 1.0f);
10282 c2[2] = bound(0.0f, c1[2], 1.0f);
10283 c2[3] = bound(0.0f, c1[3], 1.0f);
10287 static void RSurf_DrawBatch_GL11_ApplyFakeLight(float fakelightintensity)
10297 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10298 rsurface.passcolor4f_vertexbuffer = 0;
10299 rsurface.passcolor4f_bufferoffset = 0;
10300 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)
10302 f = -DotProduct(r_refdef.view.forward, n);
10304 f = f * 0.85 + 0.15; // work around so stuff won't get black
10305 f *= fakelightintensity;
10306 Vector4Set(c, f, f, f, 1);
10310 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10312 RSurf_DrawBatch_GL11_ApplyFakeLight(r_refdef.scene.lightmapintensity * r_fakelight_intensity.value);
10313 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10314 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10315 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10316 GL_Color(r, g, b, a);
10320 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, float lightmapintensity, qboolean *applycolor)
10328 vec3_t ambientcolor;
10329 vec3_t diffusecolor;
10333 VectorCopy(rsurface.texture->render_modellight_lightdir, lightdir);
10334 f = 0.5f * lightmapintensity;
10335 ambientcolor[0] = rsurface.texture->render_modellight_ambient[0] * *r * f;
10336 ambientcolor[1] = rsurface.texture->render_modellight_ambient[1] * *g * f;
10337 ambientcolor[2] = rsurface.texture->render_modellight_ambient[2] * *b * f;
10338 diffusecolor[0] = rsurface.texture->render_modellight_diffuse[0] * *r * f;
10339 diffusecolor[1] = rsurface.texture->render_modellight_diffuse[1] * *g * f;
10340 diffusecolor[2] = rsurface.texture->render_modellight_diffuse[2] * *b * f;
10342 if (VectorLength2(diffusecolor) > 0)
10344 // q3-style directional shading
10345 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10346 rsurface.passcolor4f_vertexbuffer = 0;
10347 rsurface.passcolor4f_bufferoffset = 0;
10348 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)
10350 if ((f = DotProduct(n, lightdir)) > 0)
10351 VectorMA(ambientcolor, f, diffusecolor, c);
10353 VectorCopy(ambientcolor, c);
10360 *applycolor = false;
10364 *r = ambientcolor[0];
10365 *g = ambientcolor[1];
10366 *b = ambientcolor[2];
10367 rsurface.passcolor4f = NULL;
10368 rsurface.passcolor4f_vertexbuffer = 0;
10369 rsurface.passcolor4f_bufferoffset = 0;
10373 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10375 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, r_refdef.scene.lightmapintensity, &applycolor);
10376 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
10377 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10378 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10379 GL_Color(r, g, b, a);
10383 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10391 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10392 rsurface.passcolor4f_vertexbuffer = 0;
10393 rsurface.passcolor4f_bufferoffset = 0;
10395 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10397 f = 1 - RSurf_FogVertex(v);
10405 void RSurf_SetupDepthAndCulling(void)
10407 // submodels are biased to avoid z-fighting with world surfaces that they
10408 // may be exactly overlapping (avoids z-fighting artifacts on certain
10409 // doors and things in Quake maps)
10410 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10411 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10412 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10413 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10416 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10419 // transparent sky would be ridiculous
10420 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10422 R_SetupShader_Generic_NoTexture(false, false);
10423 skyrenderlater = true;
10424 RSurf_SetupDepthAndCulling();
10425 GL_DepthMask(true);
10427 // add the vertices of the surfaces to a world bounding box so we can scissor the sky render later
10428 if (r_sky_scissor.integer)
10430 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10431 for (i = 0; i < texturenumsurfaces; i++)
10433 const msurface_t *surf = texturesurfacelist[i];
10436 float mins[3], maxs[3];
10438 for (j = 0, v = rsurface.batchvertex3f + 3 * surf->num_firstvertex; j < surf->num_vertices; j++, v += 3)
10440 Matrix4x4_Transform(&rsurface.matrix, v, p);
10443 if (mins[0] > p[0]) mins[0] = p[0];
10444 if (mins[1] > p[1]) mins[1] = p[1];
10445 if (mins[2] > p[2]) mins[2] = p[2];
10446 if (maxs[0] < p[0]) maxs[0] = p[0];
10447 if (maxs[1] < p[1]) maxs[1] = p[1];
10448 if (maxs[2] < p[2]) maxs[2] = p[2];
10452 VectorCopy(p, mins);
10453 VectorCopy(p, maxs);
10456 if (!R_ScissorForBBox(mins, maxs, scissor))
10460 if (skyscissor[0] > scissor[0])
10462 skyscissor[2] += skyscissor[0] - scissor[0];
10463 skyscissor[0] = scissor[0];
10465 if (skyscissor[1] > scissor[1])
10467 skyscissor[3] += skyscissor[1] - scissor[1];
10468 skyscissor[1] = scissor[1];
10470 if (skyscissor[0] + skyscissor[2] < scissor[0] + scissor[2])
10471 skyscissor[2] = scissor[0] + scissor[2] - skyscissor[0];
10472 if (skyscissor[1] + skyscissor[3] < scissor[1] + scissor[3])
10473 skyscissor[3] = scissor[1] + scissor[3] - skyscissor[1];
10476 Vector4Copy(scissor, skyscissor);
10481 // LadyHavoc: HalfLife maps have freaky skypolys so don't use
10482 // skymasking on them, and Quake3 never did sky masking (unlike
10483 // software Quake and software Quake2), so disable the sky masking
10484 // in Quake3 maps as it causes problems with q3map2 sky tricks,
10485 // and skymasking also looks very bad when noclipping outside the
10486 // level, so don't use it then either.
10487 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && (r_refdef.scene.worldmodel->brush.isq3bsp ? r_q3bsp_renderskydepth.integer : r_q1bsp_skymasking.integer) && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10489 R_Mesh_ResetTextureState();
10490 if (skyrendermasked)
10492 R_SetupShader_DepthOrShadow(false, false, false);
10493 // depth-only (masking)
10494 GL_ColorMask(0, 0, 0, 0);
10495 // just to make sure that braindead drivers don't draw
10496 // anything despite that colormask...
10497 GL_BlendFunc(GL_ZERO, GL_ONE);
10498 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10499 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10503 R_SetupShader_Generic_NoTexture(false, false);
10505 GL_BlendFunc(GL_ONE, GL_ZERO);
10506 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10507 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10508 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10511 if (skyrendermasked)
10512 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10514 R_Mesh_ResetTextureState();
10515 GL_Color(1, 1, 1, 1);
10518 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10519 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10520 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10522 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10526 // render screenspace normalmap to texture
10527 GL_DepthMask(true);
10528 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10533 // bind lightmap texture
10535 // water/refraction/reflection/camera surfaces have to be handled specially
10536 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10538 int start, end, startplaneindex;
10539 for (start = 0;start < texturenumsurfaces;start = end)
10541 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10542 if(startplaneindex < 0)
10544 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10545 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10549 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10551 // now that we have a batch using the same planeindex, render it
10552 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10554 // render water or distortion background
10555 GL_DepthMask(true);
10556 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10558 // blend surface on top
10559 GL_DepthMask(false);
10560 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10563 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10565 // render surface with reflection texture as input
10566 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10567 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10574 // render surface batch normally
10575 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10576 R_SetupShader_Surface(vec3_origin, vec3_origin, vec3_origin, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
10580 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10582 // OpenGL 1.3 path - anything not completely ancient
10583 qboolean applycolor;
10586 const texturelayer_t *layer;
10587 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10588 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10590 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10593 int layertexrgbscale;
10594 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10596 if (layerindex == 0)
10597 GL_AlphaTest(true);
10600 GL_AlphaTest(false);
10601 GL_DepthFunc(GL_EQUAL);
10604 GL_DepthMask(layer->depthmask && writedepth);
10605 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10606 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10608 layertexrgbscale = 4;
10609 VectorScale(layer->color, 0.25f, layercolor);
10611 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10613 layertexrgbscale = 2;
10614 VectorScale(layer->color, 0.5f, layercolor);
10618 layertexrgbscale = 1;
10619 VectorScale(layer->color, 1.0f, layercolor);
10621 layercolor[3] = layer->color[3];
10622 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10623 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10624 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10625 switch (layer->type)
10627 case TEXTURELAYERTYPE_LITTEXTURE:
10628 // single-pass lightmapped texture with 2x rgbscale
10629 R_Mesh_TexBind(0, r_texture_white);
10630 R_Mesh_TexMatrix(0, NULL);
10631 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10632 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10633 R_Mesh_TexBind(1, layer->texture);
10634 R_Mesh_TexMatrix(1, &layer->texmatrix);
10635 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10636 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10637 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10638 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10639 else if (FAKELIGHT_ENABLED)
10640 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10641 else if (rsurface.uselightmaptexture)
10642 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10644 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10646 case TEXTURELAYERTYPE_TEXTURE:
10647 // singletexture unlit texture with transparency support
10648 R_Mesh_TexBind(0, layer->texture);
10649 R_Mesh_TexMatrix(0, &layer->texmatrix);
10650 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10651 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10652 R_Mesh_TexBind(1, 0);
10653 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10654 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10656 case TEXTURELAYERTYPE_FOG:
10657 // singletexture fogging
10658 if (layer->texture)
10660 R_Mesh_TexBind(0, layer->texture);
10661 R_Mesh_TexMatrix(0, &layer->texmatrix);
10662 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10663 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10667 R_Mesh_TexBind(0, 0);
10668 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10670 R_Mesh_TexBind(1, 0);
10671 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10672 // generate a color array for the fog pass
10673 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10674 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10678 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10681 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10683 GL_DepthFunc(GL_LEQUAL);
10684 GL_AlphaTest(false);
10688 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10690 // OpenGL 1.1 - crusty old voodoo path
10693 const texturelayer_t *layer;
10694 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10695 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10697 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10699 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10701 if (layerindex == 0)
10702 GL_AlphaTest(true);
10705 GL_AlphaTest(false);
10706 GL_DepthFunc(GL_EQUAL);
10709 GL_DepthMask(layer->depthmask && writedepth);
10710 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10711 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10712 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10713 switch (layer->type)
10715 case TEXTURELAYERTYPE_LITTEXTURE:
10716 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10718 // two-pass lit texture with 2x rgbscale
10719 // first the lightmap pass
10720 R_Mesh_TexBind(0, r_texture_white);
10721 R_Mesh_TexMatrix(0, NULL);
10722 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10723 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10724 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10725 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10726 else if (FAKELIGHT_ENABLED)
10727 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10728 else if (rsurface.uselightmaptexture)
10729 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10731 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10732 // then apply the texture to it
10733 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10734 R_Mesh_TexBind(0, layer->texture);
10735 R_Mesh_TexMatrix(0, &layer->texmatrix);
10736 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10737 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10738 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);
10742 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10743 R_Mesh_TexBind(0, layer->texture);
10744 R_Mesh_TexMatrix(0, &layer->texmatrix);
10745 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10746 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10747 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10748 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);
10749 else if (FAKELIGHT_ENABLED)
10750 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);
10752 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);
10755 case TEXTURELAYERTYPE_TEXTURE:
10756 // singletexture unlit texture with transparency support
10757 R_Mesh_TexBind(0, layer->texture);
10758 R_Mesh_TexMatrix(0, &layer->texmatrix);
10759 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10760 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10761 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);
10763 case TEXTURELAYERTYPE_FOG:
10764 // singletexture fogging
10765 if (layer->texture)
10767 R_Mesh_TexBind(0, layer->texture);
10768 R_Mesh_TexMatrix(0, &layer->texmatrix);
10769 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10770 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10774 R_Mesh_TexBind(0, 0);
10775 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10777 // generate a color array for the fog pass
10778 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10779 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10783 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10786 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10788 GL_DepthFunc(GL_LEQUAL);
10789 GL_AlphaTest(false);
10793 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10797 r_vertexgeneric_t *batchvertex;
10799 texture_t *t = rsurface.texture;
10801 // R_Mesh_ResetTextureState();
10802 R_SetupShader_Generic_NoTexture(false, false);
10804 if(t && t->currentskinframe)
10806 memcpy(c, t->currentskinframe->avgcolor, sizeof(c));
10807 c[3] *= t->currentalpha;
10817 if (t->pantstexture || t->shirttexture)
10819 c[0] = 0.5 * (t->render_colormap_pants[0] * 0.3 + t->render_colormap_shirt[0] * 0.7);
10820 c[1] = 0.5 * (t->render_colormap_pants[1] * 0.3 + t->render_colormap_shirt[1] * 0.7);
10821 c[2] = 0.5 * (t->render_colormap_pants[2] * 0.3 + t->render_colormap_shirt[2] * 0.7);
10824 // brighten it up (as texture value 127 means "unlit")
10825 c[0] *= 2 * r_refdef.view.colorscale;
10826 c[1] *= 2 * r_refdef.view.colorscale;
10827 c[2] *= 2 * r_refdef.view.colorscale;
10829 if(t->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10830 c[3] *= r_wateralpha.value;
10832 if(t->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10834 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10835 GL_DepthMask(false);
10837 else if(t->currentmaterialflags & MATERIALFLAG_ADD)
10839 GL_BlendFunc(GL_ONE, GL_ONE);
10840 GL_DepthMask(false);
10842 else if(t->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10844 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10845 GL_DepthMask(false);
10847 else if(t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10849 GL_BlendFunc(t->customblendfunc[0], t->customblendfunc[1]);
10850 GL_DepthMask(false);
10854 GL_BlendFunc(GL_ONE, GL_ZERO);
10855 GL_DepthMask(writedepth);
10858 if (r_showsurfaces.integer == 3)
10860 rsurface.passcolor4f = NULL;
10862 if (t->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10864 qboolean applycolor = true;
10867 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10869 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, 1.0f, &applycolor);
10871 else if (FAKELIGHT_ENABLED)
10873 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10875 RSurf_DrawBatch_GL11_ApplyFakeLight(r_fakelight_intensity.value);
10879 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10881 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10882 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10883 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10884 RSurf_DrawBatch_GL11_ApplyAmbient();
10887 if(!rsurface.passcolor4f)
10888 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10890 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10891 if(r_refdef.fogenabled)
10892 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10893 RSurf_DrawBatch_GL11_ClampColor();
10895 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10896 R_SetupShader_Generic_NoTexture(false, false);
10899 else if (!r_refdef.view.showdebug)
10901 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10902 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10903 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10905 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10906 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10908 R_Mesh_PrepareVertices_Generic_Unlock();
10911 else if (r_showsurfaces.integer == 4)
10913 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10914 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10915 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10917 unsigned char d = (vi << 3) * (1.0f / 256.0f);
10918 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10919 Vector4Set(batchvertex[vi].color4f, d, d, d, 1);
10921 R_Mesh_PrepareVertices_Generic_Unlock();
10924 else if (r_showsurfaces.integer == 2)
10927 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10928 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10929 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10931 unsigned char d = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10932 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10933 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10934 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10935 Vector4Set(batchvertex[j*3+0].color4f, d, d, d, 1);
10936 Vector4Set(batchvertex[j*3+1].color4f, d, d, d, 1);
10937 Vector4Set(batchvertex[j*3+2].color4f, d, d, d, 1);
10939 R_Mesh_PrepareVertices_Generic_Unlock();
10940 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10944 int texturesurfaceindex;
10946 const msurface_t *surface;
10947 float surfacecolor4f[4];
10948 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10949 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10951 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10953 surface = texturesurfacelist[texturesurfaceindex];
10954 k = (int)(((size_t)surface) / sizeof(msurface_t));
10955 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10956 for (j = 0;j < surface->num_vertices;j++)
10958 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10959 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10963 R_Mesh_PrepareVertices_Generic_Unlock();
10968 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10971 RSurf_SetupDepthAndCulling();
10972 if (r_showsurfaces.integer)
10974 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10977 switch (vid.renderpath)
10979 case RENDERPATH_GL20:
10980 case RENDERPATH_D3D9:
10981 case RENDERPATH_D3D10:
10982 case RENDERPATH_D3D11:
10983 case RENDERPATH_SOFT:
10984 case RENDERPATH_GLES2:
10985 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10987 case RENDERPATH_GL13:
10988 case RENDERPATH_GLES1:
10989 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10991 case RENDERPATH_GL11:
10992 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10998 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11001 int texturenumsurfaces, endsurface;
11002 texture_t *texture;
11003 const msurface_t *surface;
11004 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11006 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11007 RSurf_ActiveModelEntity(ent, false, false, false);
11010 switch (vid.renderpath)
11012 case RENDERPATH_GL20:
11013 case RENDERPATH_D3D9:
11014 case RENDERPATH_D3D10:
11015 case RENDERPATH_D3D11:
11016 case RENDERPATH_SOFT:
11017 case RENDERPATH_GLES2:
11018 RSurf_ActiveModelEntity(ent, true, true, false);
11020 case RENDERPATH_GL11:
11021 case RENDERPATH_GL13:
11022 case RENDERPATH_GLES1:
11023 RSurf_ActiveModelEntity(ent, true, false, false);
11028 if (r_transparentdepthmasking.integer)
11030 qboolean setup = false;
11031 for (i = 0;i < numsurfaces;i = j)
11034 surface = rsurface.modelsurfaces + surfacelist[i];
11035 texture = surface->texture;
11036 rsurface.texture = R_GetCurrentTexture(texture);
11037 rsurface.lightmaptexture = NULL;
11038 rsurface.deluxemaptexture = NULL;
11039 rsurface.uselightmaptexture = false;
11040 // scan ahead until we find a different texture
11041 endsurface = min(i + 1024, numsurfaces);
11042 texturenumsurfaces = 0;
11043 texturesurfacelist[texturenumsurfaces++] = surface;
11044 for (;j < endsurface;j++)
11046 surface = rsurface.modelsurfaces + surfacelist[j];
11047 if (texture != surface->texture)
11049 texturesurfacelist[texturenumsurfaces++] = surface;
11051 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11053 // render the range of surfaces as depth
11057 GL_ColorMask(0,0,0,0);
11059 GL_DepthTest(true);
11060 GL_BlendFunc(GL_ONE, GL_ZERO);
11061 GL_DepthMask(true);
11062 // R_Mesh_ResetTextureState();
11064 RSurf_SetupDepthAndCulling();
11065 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11066 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11067 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11071 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11074 for (i = 0;i < numsurfaces;i = j)
11077 surface = rsurface.modelsurfaces + surfacelist[i];
11078 texture = surface->texture;
11079 rsurface.texture = R_GetCurrentTexture(texture);
11080 // scan ahead until we find a different texture
11081 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11082 texturenumsurfaces = 0;
11083 texturesurfacelist[texturenumsurfaces++] = surface;
11084 if(FAKELIGHT_ENABLED)
11086 rsurface.lightmaptexture = NULL;
11087 rsurface.deluxemaptexture = NULL;
11088 rsurface.uselightmaptexture = false;
11089 for (;j < endsurface;j++)
11091 surface = rsurface.modelsurfaces + surfacelist[j];
11092 if (texture != surface->texture)
11094 texturesurfacelist[texturenumsurfaces++] = surface;
11099 rsurface.lightmaptexture = surface->lightmaptexture;
11100 rsurface.deluxemaptexture = surface->deluxemaptexture;
11101 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11102 for (;j < endsurface;j++)
11104 surface = rsurface.modelsurfaces + surfacelist[j];
11105 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11107 texturesurfacelist[texturenumsurfaces++] = surface;
11110 // render the range of surfaces
11111 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11113 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
11116 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11118 // transparent surfaces get pushed off into the transparent queue
11119 int surfacelistindex;
11120 const msurface_t *surface;
11121 vec3_t tempcenter, center;
11122 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11124 surface = texturesurfacelist[surfacelistindex];
11125 if (r_transparent_sortsurfacesbynearest.integer)
11127 tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11128 tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11129 tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11133 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11134 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11135 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11137 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11138 if (rsurface.entity->transparent_offset) // transparent offset
11140 center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11141 center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11142 center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11144 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);
11148 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11150 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11152 if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11154 RSurf_SetupDepthAndCulling();
11155 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11156 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11157 R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11161 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11165 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11168 if (!rsurface.texture->currentnumlayers)
11170 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11171 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11173 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11175 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11176 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11177 else if (!rsurface.texture->currentnumlayers)
11179 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11181 // in the deferred case, transparent surfaces were queued during prepass
11182 if (!r_shadow_usingdeferredprepass)
11183 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11187 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11188 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11193 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11196 texture_t *texture;
11197 R_FrameData_SetMark();
11198 // break the surface list down into batches by texture and use of lightmapping
11199 for (i = 0;i < numsurfaces;i = j)
11202 // texture is the base texture pointer, rsurface.texture is the
11203 // current frame/skin the texture is directing us to use (for example
11204 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11205 // use skin 1 instead)
11206 texture = surfacelist[i]->texture;
11207 rsurface.texture = R_GetCurrentTexture(texture);
11208 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11210 // if this texture is not the kind we want, skip ahead to the next one
11211 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11215 if(FAKELIGHT_ENABLED || depthonly || prepass)
11217 rsurface.lightmaptexture = NULL;
11218 rsurface.deluxemaptexture = NULL;
11219 rsurface.uselightmaptexture = false;
11220 // simply scan ahead until we find a different texture or lightmap state
11221 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11226 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11227 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11228 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11229 // simply scan ahead until we find a different texture or lightmap state
11230 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11233 // render the range of surfaces
11234 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11236 R_FrameData_ReturnToMark();
11239 float locboxvertex3f[6*4*3] =
11241 1,0,1, 1,0,0, 1,1,0, 1,1,1,
11242 0,1,1, 0,1,0, 0,0,0, 0,0,1,
11243 1,1,1, 1,1,0, 0,1,0, 0,1,1,
11244 0,0,1, 0,0,0, 1,0,0, 1,0,1,
11245 0,0,1, 1,0,1, 1,1,1, 0,1,1,
11246 1,0,0, 0,0,0, 0,1,0, 1,1,0
11249 unsigned short locboxelements[6*2*3] =
11254 12,13,14, 12,14,15,
11255 16,17,18, 16,18,19,
11259 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11262 cl_locnode_t *loc = (cl_locnode_t *)ent;
11264 float vertex3f[6*4*3];
11266 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11267 GL_DepthMask(false);
11268 GL_DepthRange(0, 1);
11269 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11270 GL_DepthTest(true);
11271 GL_CullFace(GL_NONE);
11272 R_EntityMatrix(&identitymatrix);
11274 // R_Mesh_ResetTextureState();
11276 i = surfacelist[0];
11277 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11278 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11279 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11280 surfacelist[0] < 0 ? 0.5f : 0.125f);
11282 if (VectorCompare(loc->mins, loc->maxs))
11284 VectorSet(size, 2, 2, 2);
11285 VectorMA(loc->mins, -0.5f, size, mins);
11289 VectorCopy(loc->mins, mins);
11290 VectorSubtract(loc->maxs, loc->mins, size);
11293 for (i = 0;i < 6*4*3;)
11294 for (j = 0;j < 3;j++, i++)
11295 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11297 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11298 R_SetupShader_Generic_NoTexture(false, false);
11299 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11302 void R_DrawLocs(void)
11305 cl_locnode_t *loc, *nearestloc;
11307 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11308 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11310 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11311 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11315 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11317 if (decalsystem->decals)
11318 Mem_Free(decalsystem->decals);
11319 memset(decalsystem, 0, sizeof(*decalsystem));
11322 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)
11325 tridecal_t *decals;
11328 // expand or initialize the system
11329 if (decalsystem->maxdecals <= decalsystem->numdecals)
11331 decalsystem_t old = *decalsystem;
11332 qboolean useshortelements;
11333 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11334 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11335 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)));
11336 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11337 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11338 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11339 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11340 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11341 if (decalsystem->numdecals)
11342 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11344 Mem_Free(old.decals);
11345 for (i = 0;i < decalsystem->maxdecals*3;i++)
11346 decalsystem->element3i[i] = i;
11347 if (useshortelements)
11348 for (i = 0;i < decalsystem->maxdecals*3;i++)
11349 decalsystem->element3s[i] = i;
11352 // grab a decal and search for another free slot for the next one
11353 decals = decalsystem->decals;
11354 decal = decalsystem->decals + (i = decalsystem->freedecal++);
11355 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11357 decalsystem->freedecal = i;
11358 if (decalsystem->numdecals <= i)
11359 decalsystem->numdecals = i + 1;
11361 // initialize the decal
11363 decal->triangleindex = triangleindex;
11364 decal->surfaceindex = surfaceindex;
11365 decal->decalsequence = decalsequence;
11366 decal->color4f[0][0] = c0[0];
11367 decal->color4f[0][1] = c0[1];
11368 decal->color4f[0][2] = c0[2];
11369 decal->color4f[0][3] = 1;
11370 decal->color4f[1][0] = c1[0];
11371 decal->color4f[1][1] = c1[1];
11372 decal->color4f[1][2] = c1[2];
11373 decal->color4f[1][3] = 1;
11374 decal->color4f[2][0] = c2[0];
11375 decal->color4f[2][1] = c2[1];
11376 decal->color4f[2][2] = c2[2];
11377 decal->color4f[2][3] = 1;
11378 decal->vertex3f[0][0] = v0[0];
11379 decal->vertex3f[0][1] = v0[1];
11380 decal->vertex3f[0][2] = v0[2];
11381 decal->vertex3f[1][0] = v1[0];
11382 decal->vertex3f[1][1] = v1[1];
11383 decal->vertex3f[1][2] = v1[2];
11384 decal->vertex3f[2][0] = v2[0];
11385 decal->vertex3f[2][1] = v2[1];
11386 decal->vertex3f[2][2] = v2[2];
11387 decal->texcoord2f[0][0] = t0[0];
11388 decal->texcoord2f[0][1] = t0[1];
11389 decal->texcoord2f[1][0] = t1[0];
11390 decal->texcoord2f[1][1] = t1[1];
11391 decal->texcoord2f[2][0] = t2[0];
11392 decal->texcoord2f[2][1] = t2[1];
11393 TriangleNormal(v0, v1, v2, decal->plane);
11394 VectorNormalize(decal->plane);
11395 decal->plane[3] = DotProduct(v0, decal->plane);
11398 extern cvar_t cl_decals_bias;
11399 extern cvar_t cl_decals_models;
11400 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11401 // baseparms, parms, temps
11402 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)
11407 const float *vertex3f;
11408 const float *normal3f;
11410 float points[2][9][3];
11417 e = rsurface.modelelement3i + 3*triangleindex;
11419 vertex3f = rsurface.modelvertex3f;
11420 normal3f = rsurface.modelnormal3f;
11424 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11426 index = 3*e[cornerindex];
11427 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11432 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11434 index = 3*e[cornerindex];
11435 VectorCopy(vertex3f + index, v[cornerindex]);
11440 //TriangleNormal(v[0], v[1], v[2], normal);
11441 //if (DotProduct(normal, localnormal) < 0.0f)
11443 // clip by each of the box planes formed from the projection matrix
11444 // if anything survives, we emit the decal
11445 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]);
11448 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]);
11451 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]);
11454 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]);
11457 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]);
11460 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]);
11463 // some part of the triangle survived, so we have to accept it...
11466 // dynamic always uses the original triangle
11468 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11470 index = 3*e[cornerindex];
11471 VectorCopy(vertex3f + index, v[cornerindex]);
11474 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11476 // convert vertex positions to texcoords
11477 Matrix4x4_Transform(projection, v[cornerindex], temp);
11478 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11479 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11480 // calculate distance fade from the projection origin
11481 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11482 f = bound(0.0f, f, 1.0f);
11483 c[cornerindex][0] = r * f;
11484 c[cornerindex][1] = g * f;
11485 c[cornerindex][2] = b * f;
11486 c[cornerindex][3] = 1.0f;
11487 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11490 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);
11492 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11493 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);
11495 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)
11497 matrix4x4_t projection;
11498 decalsystem_t *decalsystem;
11501 const msurface_t *surface;
11502 const msurface_t *surfaces;
11503 const int *surfacelist;
11504 const texture_t *texture;
11506 int numsurfacelist;
11507 int surfacelistindex;
11510 float localorigin[3];
11511 float localnormal[3];
11512 float localmins[3];
11513 float localmaxs[3];
11516 float planes[6][4];
11519 int bih_triangles_count;
11520 int bih_triangles[256];
11521 int bih_surfaces[256];
11523 decalsystem = &ent->decalsystem;
11524 model = ent->model;
11525 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11527 R_DecalSystem_Reset(&ent->decalsystem);
11531 if (!model->brush.data_leafs && !cl_decals_models.integer)
11533 if (decalsystem->model)
11534 R_DecalSystem_Reset(decalsystem);
11538 if (decalsystem->model != model)
11539 R_DecalSystem_Reset(decalsystem);
11540 decalsystem->model = model;
11542 RSurf_ActiveModelEntity(ent, true, false, false);
11544 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11545 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11546 VectorNormalize(localnormal);
11547 localsize = worldsize*rsurface.inversematrixscale;
11548 localmins[0] = localorigin[0] - localsize;
11549 localmins[1] = localorigin[1] - localsize;
11550 localmins[2] = localorigin[2] - localsize;
11551 localmaxs[0] = localorigin[0] + localsize;
11552 localmaxs[1] = localorigin[1] + localsize;
11553 localmaxs[2] = localorigin[2] + localsize;
11555 //VectorCopy(localnormal, planes[4]);
11556 //VectorVectors(planes[4], planes[2], planes[0]);
11557 AnglesFromVectors(angles, localnormal, NULL, false);
11558 AngleVectors(angles, planes[0], planes[2], planes[4]);
11559 VectorNegate(planes[0], planes[1]);
11560 VectorNegate(planes[2], planes[3]);
11561 VectorNegate(planes[4], planes[5]);
11562 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11563 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11564 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11565 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11566 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11567 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11572 matrix4x4_t forwardprojection;
11573 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11574 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11579 float projectionvector[4][3];
11580 VectorScale(planes[0], ilocalsize, projectionvector[0]);
11581 VectorScale(planes[2], ilocalsize, projectionvector[1]);
11582 VectorScale(planes[4], ilocalsize, projectionvector[2]);
11583 projectionvector[0][0] = planes[0][0] * ilocalsize;
11584 projectionvector[0][1] = planes[1][0] * ilocalsize;
11585 projectionvector[0][2] = planes[2][0] * ilocalsize;
11586 projectionvector[1][0] = planes[0][1] * ilocalsize;
11587 projectionvector[1][1] = planes[1][1] * ilocalsize;
11588 projectionvector[1][2] = planes[2][1] * ilocalsize;
11589 projectionvector[2][0] = planes[0][2] * ilocalsize;
11590 projectionvector[2][1] = planes[1][2] * ilocalsize;
11591 projectionvector[2][2] = planes[2][2] * ilocalsize;
11592 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11593 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11594 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11595 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11599 dynamic = model->surfmesh.isanimated;
11600 numsurfacelist = model->nummodelsurfaces;
11601 surfacelist = model->sortedmodelsurfaces;
11602 surfaces = model->data_surfaces;
11605 bih_triangles_count = -1;
11608 if(model->render_bih.numleafs)
11609 bih = &model->render_bih;
11610 else if(model->collision_bih.numleafs)
11611 bih = &model->collision_bih;
11614 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11615 if(bih_triangles_count == 0)
11617 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11619 if(bih_triangles_count > 0)
11621 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11623 surfaceindex = bih_surfaces[triangleindex];
11624 surface = surfaces + surfaceindex;
11625 texture = surface->texture;
11626 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11628 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11630 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11635 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11637 surfaceindex = surfacelist[surfacelistindex];
11638 surface = surfaces + surfaceindex;
11639 // check cull box first because it rejects more than any other check
11640 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11642 // skip transparent surfaces
11643 texture = surface->texture;
11644 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11646 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11648 numtriangles = surface->num_triangles;
11649 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11650 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11655 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11656 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)
11658 int renderentityindex;
11659 float worldmins[3];
11660 float worldmaxs[3];
11661 entity_render_t *ent;
11663 if (!cl_decals_newsystem.integer)
11666 worldmins[0] = worldorigin[0] - worldsize;
11667 worldmins[1] = worldorigin[1] - worldsize;
11668 worldmins[2] = worldorigin[2] - worldsize;
11669 worldmaxs[0] = worldorigin[0] + worldsize;
11670 worldmaxs[1] = worldorigin[1] + worldsize;
11671 worldmaxs[2] = worldorigin[2] + worldsize;
11673 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11675 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11677 ent = r_refdef.scene.entities[renderentityindex];
11678 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11681 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11685 typedef struct r_decalsystem_splatqueue_s
11687 vec3_t worldorigin;
11688 vec3_t worldnormal;
11692 unsigned int decalsequence;
11694 r_decalsystem_splatqueue_t;
11696 int r_decalsystem_numqueued = 0;
11697 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11699 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)
11701 r_decalsystem_splatqueue_t *queue;
11703 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11706 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11707 VectorCopy(worldorigin, queue->worldorigin);
11708 VectorCopy(worldnormal, queue->worldnormal);
11709 Vector4Set(queue->color, r, g, b, a);
11710 Vector4Set(queue->tcrange, s1, t1, s2, t2);
11711 queue->worldsize = worldsize;
11712 queue->decalsequence = cl.decalsequence++;
11715 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11718 r_decalsystem_splatqueue_t *queue;
11720 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11721 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);
11722 r_decalsystem_numqueued = 0;
11725 extern cvar_t cl_decals_max;
11726 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11729 decalsystem_t *decalsystem = &ent->decalsystem;
11731 unsigned int killsequence;
11736 if (!decalsystem->numdecals)
11739 if (r_showsurfaces.integer)
11742 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11744 R_DecalSystem_Reset(decalsystem);
11748 killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
11749 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11751 if (decalsystem->lastupdatetime)
11752 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11755 decalsystem->lastupdatetime = r_refdef.scene.time;
11756 numdecals = decalsystem->numdecals;
11758 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11760 if (decal->color4f[0][3])
11762 decal->lived += frametime;
11763 if (killsequence > decal->decalsequence || decal->lived >= lifetime)
11765 memset(decal, 0, sizeof(*decal));
11766 if (decalsystem->freedecal > i)
11767 decalsystem->freedecal = i;
11771 decal = decalsystem->decals;
11772 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11775 // collapse the array by shuffling the tail decals into the gaps
11778 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11779 decalsystem->freedecal++;
11780 if (decalsystem->freedecal == numdecals)
11782 decal[decalsystem->freedecal] = decal[--numdecals];
11785 decalsystem->numdecals = numdecals;
11787 if (numdecals <= 0)
11789 // if there are no decals left, reset decalsystem
11790 R_DecalSystem_Reset(decalsystem);
11794 extern skinframe_t *decalskinframe;
11795 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11798 decalsystem_t *decalsystem = &ent->decalsystem;
11807 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11810 numdecals = decalsystem->numdecals;
11814 if (r_showsurfaces.integer)
11817 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11819 R_DecalSystem_Reset(decalsystem);
11823 // if the model is static it doesn't matter what value we give for
11824 // wantnormals and wanttangents, so this logic uses only rules applicable
11825 // to a model, knowing that they are meaningless otherwise
11826 RSurf_ActiveModelEntity(ent, false, false, false);
11828 decalsystem->lastupdatetime = r_refdef.scene.time;
11830 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11832 // update vertex positions for animated models
11833 v3f = decalsystem->vertex3f;
11834 c4f = decalsystem->color4f;
11835 t2f = decalsystem->texcoord2f;
11836 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11838 if (!decal->color4f[0][3])
11841 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11845 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11848 // update color values for fading decals
11849 if (decal->lived >= cl_decals_time.value)
11850 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11854 c4f[ 0] = decal->color4f[0][0] * alpha;
11855 c4f[ 1] = decal->color4f[0][1] * alpha;
11856 c4f[ 2] = decal->color4f[0][2] * alpha;
11858 c4f[ 4] = decal->color4f[1][0] * alpha;
11859 c4f[ 5] = decal->color4f[1][1] * alpha;
11860 c4f[ 6] = decal->color4f[1][2] * alpha;
11862 c4f[ 8] = decal->color4f[2][0] * alpha;
11863 c4f[ 9] = decal->color4f[2][1] * alpha;
11864 c4f[10] = decal->color4f[2][2] * alpha;
11867 t2f[0] = decal->texcoord2f[0][0];
11868 t2f[1] = decal->texcoord2f[0][1];
11869 t2f[2] = decal->texcoord2f[1][0];
11870 t2f[3] = decal->texcoord2f[1][1];
11871 t2f[4] = decal->texcoord2f[2][0];
11872 t2f[5] = decal->texcoord2f[2][1];
11874 // update vertex positions for animated models
11875 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11877 e = rsurface.modelelement3i + 3*decal->triangleindex;
11878 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11879 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11880 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11884 VectorCopy(decal->vertex3f[0], v3f);
11885 VectorCopy(decal->vertex3f[1], v3f + 3);
11886 VectorCopy(decal->vertex3f[2], v3f + 6);
11889 if (r_refdef.fogenabled)
11891 alpha = RSurf_FogVertex(v3f);
11892 VectorScale(c4f, alpha, c4f);
11893 alpha = RSurf_FogVertex(v3f + 3);
11894 VectorScale(c4f + 4, alpha, c4f + 4);
11895 alpha = RSurf_FogVertex(v3f + 6);
11896 VectorScale(c4f + 8, alpha, c4f + 8);
11907 r_refdef.stats[r_stat_drawndecals] += numtris;
11909 // now render the decals all at once
11910 // (this assumes they all use one particle font texture!)
11911 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);
11912 // R_Mesh_ResetTextureState();
11913 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11914 GL_DepthMask(false);
11915 GL_DepthRange(0, 1);
11916 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11917 GL_DepthTest(true);
11918 GL_CullFace(GL_NONE);
11919 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11920 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11921 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11925 static void R_DrawModelDecals(void)
11929 // fade faster when there are too many decals
11930 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11931 for (i = 0;i < r_refdef.scene.numentities;i++)
11932 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11934 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11935 for (i = 0;i < r_refdef.scene.numentities;i++)
11936 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11937 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11939 R_DecalSystem_ApplySplatEntitiesQueue();
11941 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11942 for (i = 0;i < r_refdef.scene.numentities;i++)
11943 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11945 r_refdef.stats[r_stat_totaldecals] += numdecals;
11947 if (r_showsurfaces.integer)
11950 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11952 for (i = 0;i < r_refdef.scene.numentities;i++)
11954 if (!r_refdef.viewcache.entityvisible[i])
11956 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11957 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11961 extern cvar_t mod_collision_bih;
11962 static void R_DrawDebugModel(void)
11964 entity_render_t *ent = rsurface.entity;
11965 int i, j, flagsmask;
11966 const msurface_t *surface;
11967 dp_model_t *model = ent->model;
11969 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11972 if (r_showoverdraw.value > 0)
11974 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11975 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11976 R_SetupShader_Generic_NoTexture(false, false);
11977 GL_DepthTest(false);
11978 GL_DepthMask(false);
11979 GL_DepthRange(0, 1);
11980 GL_BlendFunc(GL_ONE, GL_ONE);
11981 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11983 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11985 rsurface.texture = R_GetCurrentTexture(surface->texture);
11986 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11988 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11989 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11990 if (!rsurface.texture->currentlayers->depthmask)
11991 GL_Color(c, 0, 0, 1.0f);
11992 else if (ent == r_refdef.scene.worldentity)
11993 GL_Color(c, c, c, 1.0f);
11995 GL_Color(0, c, 0, 1.0f);
11996 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12000 rsurface.texture = NULL;
12003 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12005 // R_Mesh_ResetTextureState();
12006 R_SetupShader_Generic_NoTexture(false, false);
12007 GL_DepthRange(0, 1);
12008 GL_DepthTest(!r_showdisabledepthtest.integer);
12009 GL_DepthMask(false);
12010 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12012 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12016 qboolean cullbox = false;
12017 const q3mbrush_t *brush;
12018 const bih_t *bih = &model->collision_bih;
12019 const bih_leaf_t *bihleaf;
12020 float vertex3f[3][3];
12021 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12022 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12024 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12026 switch (bihleaf->type)
12029 brush = model->brush.data_brushes + bihleaf->itemindex;
12030 if (brush->colbrushf && brush->colbrushf->numtriangles)
12032 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);
12033 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12034 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12037 case BIH_COLLISIONTRIANGLE:
12038 triangleindex = bihleaf->itemindex;
12039 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12040 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12041 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12042 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);
12043 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12044 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12046 case BIH_RENDERTRIANGLE:
12047 triangleindex = bihleaf->itemindex;
12048 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12049 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12050 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12051 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);
12052 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12053 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12059 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12062 if (r_showtris.value > 0 && qglPolygonMode)
12064 if (r_showdisabledepthtest.integer)
12066 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12067 GL_DepthMask(false);
12071 GL_BlendFunc(GL_ONE, GL_ZERO);
12072 GL_DepthMask(true);
12074 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12075 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12077 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12079 rsurface.texture = R_GetCurrentTexture(surface->texture);
12080 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12082 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12083 if (!rsurface.texture->currentlayers->depthmask)
12084 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12085 else if (ent == r_refdef.scene.worldentity)
12086 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12088 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12089 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12093 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12094 rsurface.texture = NULL;
12097 if (r_shownormals.value != 0 && qglBegin)
12101 if (r_showdisabledepthtest.integer)
12103 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12104 GL_DepthMask(false);
12108 GL_BlendFunc(GL_ONE, GL_ZERO);
12109 GL_DepthMask(true);
12111 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12113 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12115 rsurface.texture = R_GetCurrentTexture(surface->texture);
12116 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12118 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12119 qglBegin(GL_LINES);
12120 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12122 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12124 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12125 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12126 qglVertex3f(v[0], v[1], v[2]);
12127 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12128 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12129 qglVertex3f(v[0], v[1], v[2]);
12132 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12134 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12136 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12137 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12138 qglVertex3f(v[0], v[1], v[2]);
12139 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12140 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12141 qglVertex3f(v[0], v[1], v[2]);
12144 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12146 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12148 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12149 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12150 qglVertex3f(v[0], v[1], v[2]);
12151 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12152 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12153 qglVertex3f(v[0], v[1], v[2]);
12156 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12158 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12160 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12161 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12162 qglVertex3f(v[0], v[1], v[2]);
12163 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12164 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12165 qglVertex3f(v[0], v[1], v[2]);
12172 rsurface.texture = NULL;
12177 int r_maxsurfacelist = 0;
12178 const msurface_t **r_surfacelist = NULL;
12179 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12181 int i, j, endj, flagsmask;
12182 dp_model_t *model = ent->model;
12183 msurface_t *surfaces;
12184 unsigned char *update;
12185 int numsurfacelist = 0;
12189 if (r_maxsurfacelist < model->num_surfaces)
12191 r_maxsurfacelist = model->num_surfaces;
12193 Mem_Free((msurface_t **)r_surfacelist);
12194 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12197 if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12198 RSurf_ActiveModelEntity(ent, false, false, false);
12200 RSurf_ActiveModelEntity(ent, true, true, true);
12201 else if (depthonly)
12203 switch (vid.renderpath)
12205 case RENDERPATH_GL20:
12206 case RENDERPATH_D3D9:
12207 case RENDERPATH_D3D10:
12208 case RENDERPATH_D3D11:
12209 case RENDERPATH_SOFT:
12210 case RENDERPATH_GLES2:
12211 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12213 case RENDERPATH_GL11:
12214 case RENDERPATH_GL13:
12215 case RENDERPATH_GLES1:
12216 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12222 switch (vid.renderpath)
12224 case RENDERPATH_GL20:
12225 case RENDERPATH_D3D9:
12226 case RENDERPATH_D3D10:
12227 case RENDERPATH_D3D11:
12228 case RENDERPATH_SOFT:
12229 case RENDERPATH_GLES2:
12230 RSurf_ActiveModelEntity(ent, true, true, false);
12232 case RENDERPATH_GL11:
12233 case RENDERPATH_GL13:
12234 case RENDERPATH_GLES1:
12235 RSurf_ActiveModelEntity(ent, true, false, false);
12240 surfaces = model->data_surfaces;
12241 update = model->brushq1.lightmapupdateflags;
12243 // update light styles
12244 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.scene.lightmapintensity > 0)
12246 model_brush_lightstyleinfo_t *style;
12247 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12249 if (style->value != r_refdef.scene.lightstylevalue[style->style])
12251 int *list = style->surfacelist;
12252 style->value = r_refdef.scene.lightstylevalue[style->style];
12253 for (j = 0;j < style->numsurfaces;j++)
12254 update[list[j]] = true;
12259 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12263 R_DrawDebugModel();
12264 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12268 rsurface.lightmaptexture = NULL;
12269 rsurface.deluxemaptexture = NULL;
12270 rsurface.uselightmaptexture = false;
12271 rsurface.texture = NULL;
12272 rsurface.rtlight = NULL;
12273 numsurfacelist = 0;
12274 // add visible surfaces to draw list
12275 if (ent == r_refdef.scene.worldentity)
12277 // for the world entity, check surfacevisible
12278 for (i = 0;i < model->nummodelsurfaces;i++)
12280 j = model->sortedmodelsurfaces[i];
12281 if (r_refdef.viewcache.world_surfacevisible[j])
12282 r_surfacelist[numsurfacelist++] = surfaces + j;
12287 // add all surfaces
12288 for (i = 0; i < model->nummodelsurfaces; i++)
12289 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12291 // don't do anything if there were no surfaces
12292 if (!numsurfacelist)
12294 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12297 // update lightmaps if needed
12301 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12306 R_BuildLightMap(ent, surfaces + j);
12311 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12313 // add to stats if desired
12314 if (r_speeds.integer && !skysurfaces && !depthonly)
12316 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12317 for (j = 0;j < numsurfacelist;j++)
12318 r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12321 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveModelEntity
12324 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12327 static texture_t texture;
12328 static msurface_t surface;
12329 const msurface_t *surfacelist = &surface;
12331 // fake enough texture and surface state to render this geometry
12333 texture.update_lastrenderframe = -1; // regenerate this texture
12334 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12335 texture.basealpha = 1.0f;
12336 texture.currentskinframe = skinframe;
12337 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12338 texture.offsetmapping = OFFSETMAPPING_OFF;
12339 texture.offsetscale = 1;
12340 texture.specularscalemod = 1;
12341 texture.specularpowermod = 1;
12342 texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12343 // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12344 // JUST GREP FOR "specularscalemod = 1".
12346 for (q = 0; q < 3; q++)
12348 texture.render_glowmod[q] = r_refdef.view.colorscale * r_hdr_glowintensity.value;
12349 texture.render_modellight_lightdir[q] = q == 2;
12350 texture.render_modellight_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12351 texture.render_modellight_diffuse[q] = r_refdef.view.colorscale;
12352 texture.render_modellight_specular[q] = r_refdef.view.colorscale;
12353 texture.render_lightmap_ambient[q] = r_refdef.view.colorscale * r_refdef.scene.ambientintensity;
12354 texture.render_lightmap_diffuse[q] = r_refdef.view.colorscale * r_refdef.scene.lightmapintensity;
12355 texture.render_lightmap_specular[q] = r_refdef.view.colorscale;
12356 texture.render_rtlight_diffuse[q] = r_refdef.view.colorscale;
12357 texture.render_rtlight_specular[q] = r_refdef.view.colorscale;
12359 texture.currentalpha = 1.0f;
12361 surface.texture = &texture;
12362 surface.num_triangles = numtriangles;
12363 surface.num_firsttriangle = firsttriangle;
12364 surface.num_vertices = numvertices;
12365 surface.num_firstvertex = firstvertex;
12368 rsurface.texture = R_GetCurrentTexture(surface.texture);
12369 rsurface.lightmaptexture = NULL;
12370 rsurface.deluxemaptexture = NULL;
12371 rsurface.uselightmaptexture = false;
12372 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12375 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)
12377 static msurface_t surface;
12378 const msurface_t *surfacelist = &surface;
12380 // fake enough texture and surface state to render this geometry
12381 surface.texture = texture;
12382 surface.num_triangles = numtriangles;
12383 surface.num_firsttriangle = firsttriangle;
12384 surface.num_vertices = numvertices;
12385 surface.num_firstvertex = firstvertex;
12388 rsurface.texture = R_GetCurrentTexture(surface.texture);
12389 rsurface.lightmaptexture = NULL;
12390 rsurface.deluxemaptexture = NULL;
12391 rsurface.uselightmaptexture = false;
12392 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);