2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include "cl_dyntexture.h"
30 #include "dpsoftrast.h"
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 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"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 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)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
68 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"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
76 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
77 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)"};
78 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
79 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
80 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"};
81 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"};
82 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
83 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"};
84 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"};
85 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"};
86 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
87 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
88 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
89 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
90 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
91 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
92 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
93 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)"};
94 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)"};
95 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
96 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
97 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
98 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
101 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
102 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
105 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
106 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
107 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."};
108 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
109 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
110 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
111 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."};
112 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
113 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
114 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
115 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
116 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"};
117 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"};
118 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
119 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
121 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
122 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
123 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"};
124 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
125 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
128 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
129 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
130 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
131 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
132 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
133 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
134 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136 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)"};
137 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"};
139 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
142 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
143 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
144 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
145 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
147 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
148 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
149 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
151 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"};
152 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"};
153 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
154 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
155 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"};
156 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)"};
157 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)"};
158 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
160 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)"};
161 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
164 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)"};
165 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)"};
166 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
185 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
186 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
187 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
189 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
190 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
191 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
192 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
193 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
194 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
195 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
197 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
198 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
199 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
200 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
201 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
202 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
203 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
206 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
208 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"};
210 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"};
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
216 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
217 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
218 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
219 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
220 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
221 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
222 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
227 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."};
229 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)"};
231 extern cvar_t v_glslgamma;
233 extern qboolean v_flipped_state;
235 static struct r_bloomstate_s
240 int bloomwidth, bloomheight;
242 textype_t texturetype;
243 int viewfbo; // used to check if r_viewfbo cvar has changed
245 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
246 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
247 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
249 int screentexturewidth, screentextureheight;
250 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
252 int bloomtexturewidth, bloomtextureheight;
253 rtexture_t *texture_bloom;
255 // arrays for rendering the screen passes
256 float screentexcoord2f[8];
257 float bloomtexcoord2f[8];
258 float offsettexcoord2f[8];
260 r_viewport_t viewport;
264 r_waterstate_t r_waterstate;
266 /// shadow volume bsp struct with automatically growing nodes buffer
269 rtexture_t *r_texture_blanknormalmap;
270 rtexture_t *r_texture_white;
271 rtexture_t *r_texture_grey128;
272 rtexture_t *r_texture_black;
273 rtexture_t *r_texture_notexture;
274 rtexture_t *r_texture_whitecube;
275 rtexture_t *r_texture_normalizationcube;
276 rtexture_t *r_texture_fogattenuation;
277 rtexture_t *r_texture_fogheighttexture;
278 rtexture_t *r_texture_gammaramps;
279 unsigned int r_texture_gammaramps_serial;
280 //rtexture_t *r_texture_fogintensity;
281 rtexture_t *r_texture_reflectcube;
283 // TODO: hash lookups?
284 typedef struct cubemapinfo_s
291 int r_texture_numcubemaps;
292 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
294 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
295 unsigned int r_numqueries;
296 unsigned int r_maxqueries;
298 typedef struct r_qwskincache_s
300 char name[MAX_QPATH];
301 skinframe_t *skinframe;
305 static r_qwskincache_t *r_qwskincache;
306 static int r_qwskincache_size;
308 /// vertex coordinates for a quad that covers the screen exactly
309 extern const float r_screenvertex3f[12];
310 extern const float r_d3dscreenvertex3f[12];
311 const float r_screenvertex3f[12] =
318 const float r_d3dscreenvertex3f[12] =
326 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
329 for (i = 0;i < verts;i++)
340 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
343 for (i = 0;i < verts;i++)
353 // FIXME: move this to client?
356 if (gamemode == GAME_NEHAHRA)
358 Cvar_Set("gl_fogenable", "0");
359 Cvar_Set("gl_fogdensity", "0.2");
360 Cvar_Set("gl_fogred", "0.3");
361 Cvar_Set("gl_foggreen", "0.3");
362 Cvar_Set("gl_fogblue", "0.3");
364 r_refdef.fog_density = 0;
365 r_refdef.fog_red = 0;
366 r_refdef.fog_green = 0;
367 r_refdef.fog_blue = 0;
368 r_refdef.fog_alpha = 1;
369 r_refdef.fog_start = 0;
370 r_refdef.fog_end = 16384;
371 r_refdef.fog_height = 1<<30;
372 r_refdef.fog_fadedepth = 128;
373 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
376 static void R_BuildBlankTextures(void)
378 unsigned char data[4];
379 data[2] = 128; // normal X
380 data[1] = 128; // normal Y
381 data[0] = 255; // normal Z
382 data[3] = 128; // height
383 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
401 static void R_BuildNoTexture(void)
404 unsigned char pix[16][16][4];
405 // this makes a light grey/dark grey checkerboard texture
406 for (y = 0;y < 16;y++)
408 for (x = 0;x < 16;x++)
410 if ((y < 8) ^ (x < 8))
426 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
429 static void R_BuildWhiteCube(void)
431 unsigned char data[6*1*1*4];
432 memset(data, 255, sizeof(data));
433 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
436 static void R_BuildNormalizationCube(void)
440 vec_t s, t, intensity;
443 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
444 for (side = 0;side < 6;side++)
446 for (y = 0;y < NORMSIZE;y++)
448 for (x = 0;x < NORMSIZE;x++)
450 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
451 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
486 intensity = 127.0f / sqrt(DotProduct(v, v));
487 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
488 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
489 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
490 data[((side*64+y)*64+x)*4+3] = 255;
494 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
498 static void R_BuildFogTexture(void)
502 unsigned char data1[FOGWIDTH][4];
503 //unsigned char data2[FOGWIDTH][4];
506 r_refdef.fogmasktable_start = r_refdef.fog_start;
507 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
508 r_refdef.fogmasktable_range = r_refdef.fogrange;
509 r_refdef.fogmasktable_density = r_refdef.fog_density;
511 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
512 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
514 d = (x * r - r_refdef.fogmasktable_start);
515 if(developer_extra.integer)
516 Con_DPrintf("%f ", d);
518 if (r_fog_exp2.integer)
519 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
521 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
522 if(developer_extra.integer)
523 Con_DPrintf(" : %f ", alpha);
524 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
525 if(developer_extra.integer)
526 Con_DPrintf(" = %f\n", alpha);
527 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
530 for (x = 0;x < FOGWIDTH;x++)
532 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537 //data2[x][0] = 255 - b;
538 //data2[x][1] = 255 - b;
539 //data2[x][2] = 255 - b;
542 if (r_texture_fogattenuation)
544 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
550 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
554 static void R_BuildFogHeightTexture(void)
556 unsigned char *inpixels;
564 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
565 if (r_refdef.fogheighttexturename[0])
566 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
569 r_refdef.fog_height_tablesize = 0;
570 if (r_texture_fogheighttexture)
571 R_FreeTexture(r_texture_fogheighttexture);
572 r_texture_fogheighttexture = NULL;
573 if (r_refdef.fog_height_table2d)
574 Mem_Free(r_refdef.fog_height_table2d);
575 r_refdef.fog_height_table2d = NULL;
576 if (r_refdef.fog_height_table1d)
577 Mem_Free(r_refdef.fog_height_table1d);
578 r_refdef.fog_height_table1d = NULL;
582 r_refdef.fog_height_tablesize = size;
583 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
584 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
585 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
587 // LordHavoc: now the magic - what is that table2d for? it is a cooked
588 // average fog color table accounting for every fog layer between a point
589 // and the camera. (Note: attenuation is handled separately!)
590 for (y = 0;y < size;y++)
592 for (x = 0;x < size;x++)
598 for (j = x;j <= y;j++)
600 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606 for (j = x;j >= y;j--)
608 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
614 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
615 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
616 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
619 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
622 //=======================================================================================================================================================
624 static const char *builtinshaderstring =
625 #include "shader_glsl.h"
628 const char *builtinhlslshaderstring =
629 #include "shader_hlsl.h"
632 char *glslshaderstring = NULL;
633 char *hlslshaderstring = NULL;
635 //=======================================================================================================================================================
637 typedef struct shaderpermutationinfo_s
642 shaderpermutationinfo_t;
644 typedef struct shadermodeinfo_s
646 const char *vertexfilename;
647 const char *geometryfilename;
648 const char *fragmentfilename;
654 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
655 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
657 {"#define USEDIFFUSE\n", " diffuse"},
658 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
659 {"#define USEVIEWTINT\n", " viewtint"},
660 {"#define USECOLORMAPPING\n", " colormapping"},
661 {"#define USESATURATION\n", " saturation"},
662 {"#define USEFOGINSIDE\n", " foginside"},
663 {"#define USEFOGOUTSIDE\n", " fogoutside"},
664 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
665 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
666 {"#define USEGAMMARAMPS\n", " gammaramps"},
667 {"#define USECUBEFILTER\n", " cubefilter"},
668 {"#define USEGLOW\n", " glow"},
669 {"#define USEBLOOM\n", " bloom"},
670 {"#define USESPECULAR\n", " specular"},
671 {"#define USEPOSTPROCESSING\n", " postprocessing"},
672 {"#define USEREFLECTION\n", " reflection"},
673 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
674 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
675 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
676 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
677 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
678 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
679 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
680 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
681 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
682 {"#define USEALPHAKILL\n", " alphakill"},
683 {"#define USEREFLECTCUBE\n", " reflectcube"},
684 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
685 {"#define USEBOUNCEGRID\n", " bouncegrid"},
686 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
689 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
690 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
694 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
704 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
705 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
710 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
734 struct r_glsl_permutation_s *hashnext;
736 unsigned int permutation;
738 /// indicates if we have tried compiling this permutation already
740 /// 0 if compilation failed
742 // texture units assigned to each detected uniform
743 int tex_Texture_First;
744 int tex_Texture_Second;
745 int tex_Texture_GammaRamps;
746 int tex_Texture_Normal;
747 int tex_Texture_Color;
748 int tex_Texture_Gloss;
749 int tex_Texture_Glow;
750 int tex_Texture_SecondaryNormal;
751 int tex_Texture_SecondaryColor;
752 int tex_Texture_SecondaryGloss;
753 int tex_Texture_SecondaryGlow;
754 int tex_Texture_Pants;
755 int tex_Texture_Shirt;
756 int tex_Texture_FogHeightTexture;
757 int tex_Texture_FogMask;
758 int tex_Texture_Lightmap;
759 int tex_Texture_Deluxemap;
760 int tex_Texture_Attenuation;
761 int tex_Texture_Cube;
762 int tex_Texture_Refraction;
763 int tex_Texture_Reflection;
764 int tex_Texture_ShadowMap2D;
765 int tex_Texture_CubeProjection;
766 int tex_Texture_ScreenDepth;
767 int tex_Texture_ScreenNormalMap;
768 int tex_Texture_ScreenDiffuse;
769 int tex_Texture_ScreenSpecular;
770 int tex_Texture_ReflectMask;
771 int tex_Texture_ReflectCube;
772 int tex_Texture_BounceGrid;
773 /// locations of detected uniforms in program object, or -1 if not found
774 int loc_Texture_First;
775 int loc_Texture_Second;
776 int loc_Texture_GammaRamps;
777 int loc_Texture_Normal;
778 int loc_Texture_Color;
779 int loc_Texture_Gloss;
780 int loc_Texture_Glow;
781 int loc_Texture_SecondaryNormal;
782 int loc_Texture_SecondaryColor;
783 int loc_Texture_SecondaryGloss;
784 int loc_Texture_SecondaryGlow;
785 int loc_Texture_Pants;
786 int loc_Texture_Shirt;
787 int loc_Texture_FogHeightTexture;
788 int loc_Texture_FogMask;
789 int loc_Texture_Lightmap;
790 int loc_Texture_Deluxemap;
791 int loc_Texture_Attenuation;
792 int loc_Texture_Cube;
793 int loc_Texture_Refraction;
794 int loc_Texture_Reflection;
795 int loc_Texture_ShadowMap2D;
796 int loc_Texture_CubeProjection;
797 int loc_Texture_ScreenDepth;
798 int loc_Texture_ScreenNormalMap;
799 int loc_Texture_ScreenDiffuse;
800 int loc_Texture_ScreenSpecular;
801 int loc_Texture_ReflectMask;
802 int loc_Texture_ReflectCube;
803 int loc_Texture_BounceGrid;
805 int loc_BloomBlur_Parameters;
807 int loc_Color_Ambient;
808 int loc_Color_Diffuse;
809 int loc_Color_Specular;
813 int loc_DeferredColor_Ambient;
814 int loc_DeferredColor_Diffuse;
815 int loc_DeferredColor_Specular;
816 int loc_DeferredMod_Diffuse;
817 int loc_DeferredMod_Specular;
818 int loc_DistortScaleRefractReflect;
821 int loc_FogHeightFade;
823 int loc_FogPlaneViewDist;
824 int loc_FogRangeRecip;
827 int loc_LightPosition;
828 int loc_OffsetMapping_ScaleSteps;
830 int loc_ReflectColor;
831 int loc_ReflectFactor;
832 int loc_ReflectOffset;
833 int loc_RefractColor;
835 int loc_ScreenCenterRefractReflect;
836 int loc_ScreenScaleRefractReflect;
837 int loc_ScreenToDepth;
838 int loc_ShadowMap_Parameters;
839 int loc_ShadowMap_TextureScale;
840 int loc_SpecularPower;
845 int loc_ViewTintColor;
847 int loc_ModelToLight;
849 int loc_BackgroundTexMatrix;
850 int loc_ModelViewProjectionMatrix;
851 int loc_ModelViewMatrix;
852 int loc_PixelToScreenTexCoord;
853 int loc_ModelToReflectCube;
854 int loc_ShadowMapMatrix;
855 int loc_BloomColorSubtract;
856 int loc_NormalmapScrollBlend;
857 int loc_BounceGridMatrix;
858 int loc_BounceGridIntensity;
860 r_glsl_permutation_t;
862 #define SHADERPERMUTATION_HASHSIZE 256
865 // non-degradable "lightweight" shader parameters to keep the permutations simpler
866 // these can NOT degrade! only use for simple stuff
869 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
870 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
871 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
872 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
873 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
874 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
875 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
877 #define SHADERSTATICPARMS_COUNT 7
879 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
880 static int shaderstaticparms_count = 0;
882 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
883 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
884 qboolean R_CompileShader_CheckStaticParms(void)
886 static int r_compileshader_staticparms_save[1];
887 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
888 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
891 if (r_glsl_saturation_redcompensate.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
893 if (r_glsl_vertextextureblend_usebothalphas.integer)
894 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
895 if (r_shadow_glossexact.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
897 if (r_glsl_postprocess.integer)
899 if (r_glsl_postprocess_uservec1_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
901 if (r_glsl_postprocess_uservec2_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
903 if (r_glsl_postprocess_uservec3_enable.integer)
904 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
905 if (r_glsl_postprocess_uservec4_enable.integer)
906 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
908 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
911 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
912 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
913 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
915 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
916 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
918 shaderstaticparms_count = 0;
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
924 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
925 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
926 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
927 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
930 /// information about each possible shader permutation
931 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
932 /// currently selected permutation
933 r_glsl_permutation_t *r_glsl_permutation;
934 /// storage for permutations linked in the hash table
935 memexpandablearray_t r_glsl_permutationarray;
937 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
939 //unsigned int hashdepth = 0;
940 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
941 r_glsl_permutation_t *p;
942 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
944 if (p->mode == mode && p->permutation == permutation)
946 //if (hashdepth > 10)
947 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
952 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
954 p->permutation = permutation;
955 p->hashnext = r_glsl_permutationhash[mode][hashindex];
956 r_glsl_permutationhash[mode][hashindex] = p;
957 //if (hashdepth > 10)
958 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
962 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
965 if (!filename || !filename[0])
967 if (!strcmp(filename, "glsl/default.glsl"))
969 if (!glslshaderstring)
971 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
972 if (glslshaderstring)
973 Con_DPrintf("Loading shaders from file %s...\n", filename);
975 glslshaderstring = (char *)builtinshaderstring;
977 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
978 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
981 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
984 if (printfromdisknotice)
985 Con_DPrintf("from disk %s... ", filename);
991 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
995 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
996 char *vertexstring, *geometrystring, *fragmentstring;
997 char permutationname[256];
998 int vertstrings_count = 0;
999 int geomstrings_count = 0;
1000 int fragstrings_count = 0;
1001 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1003 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010 permutationname[0] = 0;
1011 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1012 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1013 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1015 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1017 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1018 if(vid.support.gl20shaders130)
1020 vertstrings_list[vertstrings_count++] = "#version 130\n";
1021 geomstrings_list[geomstrings_count++] = "#version 130\n";
1022 fragstrings_list[fragstrings_count++] = "#version 130\n";
1023 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1024 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1025 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1028 // the first pretext is which type of shader to compile as
1029 // (later these will all be bound together as a program object)
1030 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1031 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1032 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1034 // the second pretext is the mode (for example a light source)
1035 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1036 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1037 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1038 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1040 // now add all the permutation pretexts
1041 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1043 if (permutation & (1<<i))
1045 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1046 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1047 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1048 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1052 // keep line numbers correct
1053 vertstrings_list[vertstrings_count++] = "\n";
1054 geomstrings_list[geomstrings_count++] = "\n";
1055 fragstrings_list[fragstrings_count++] = "\n";
1060 R_CompileShader_AddStaticParms(mode, permutation);
1061 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062 vertstrings_count += shaderstaticparms_count;
1063 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064 geomstrings_count += shaderstaticparms_count;
1065 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1066 fragstrings_count += shaderstaticparms_count;
1068 // now append the shader text itself
1069 vertstrings_list[vertstrings_count++] = vertexstring;
1070 geomstrings_list[geomstrings_count++] = geometrystring;
1071 fragstrings_list[fragstrings_count++] = fragmentstring;
1073 // if any sources were NULL, clear the respective list
1075 vertstrings_count = 0;
1076 if (!geometrystring)
1077 geomstrings_count = 0;
1078 if (!fragmentstring)
1079 fragstrings_count = 0;
1081 // compile the shader program
1082 if (vertstrings_count + geomstrings_count + fragstrings_count)
1083 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1087 qglUseProgram(p->program);CHECKGLERROR
1088 // look up all the uniform variable names we care about, so we don't
1089 // have to look them up every time we set them
1091 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1092 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1093 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1094 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1095 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1096 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1097 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1098 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1099 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1100 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1101 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1102 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1103 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1104 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1105 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1106 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1107 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1108 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1109 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1110 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1111 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1112 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1113 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1114 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1115 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1116 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1117 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1118 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1119 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1120 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1121 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1122 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1123 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1124 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1125 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1126 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1127 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1128 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1129 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1130 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1131 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1132 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1133 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1134 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1135 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1136 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1137 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1138 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1139 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1140 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1141 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1142 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1143 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1144 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1145 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1146 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1147 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1148 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1149 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1150 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1151 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1152 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1153 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1154 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1155 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1156 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1157 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1158 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1159 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1160 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1161 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1162 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1163 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1164 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1165 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1166 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1167 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1168 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1169 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1170 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1171 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1172 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1173 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1174 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1175 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1176 // initialize the samplers to refer to the texture units we use
1177 p->tex_Texture_First = -1;
1178 p->tex_Texture_Second = -1;
1179 p->tex_Texture_GammaRamps = -1;
1180 p->tex_Texture_Normal = -1;
1181 p->tex_Texture_Color = -1;
1182 p->tex_Texture_Gloss = -1;
1183 p->tex_Texture_Glow = -1;
1184 p->tex_Texture_SecondaryNormal = -1;
1185 p->tex_Texture_SecondaryColor = -1;
1186 p->tex_Texture_SecondaryGloss = -1;
1187 p->tex_Texture_SecondaryGlow = -1;
1188 p->tex_Texture_Pants = -1;
1189 p->tex_Texture_Shirt = -1;
1190 p->tex_Texture_FogHeightTexture = -1;
1191 p->tex_Texture_FogMask = -1;
1192 p->tex_Texture_Lightmap = -1;
1193 p->tex_Texture_Deluxemap = -1;
1194 p->tex_Texture_Attenuation = -1;
1195 p->tex_Texture_Cube = -1;
1196 p->tex_Texture_Refraction = -1;
1197 p->tex_Texture_Reflection = -1;
1198 p->tex_Texture_ShadowMap2D = -1;
1199 p->tex_Texture_CubeProjection = -1;
1200 p->tex_Texture_ScreenDepth = -1;
1201 p->tex_Texture_ScreenNormalMap = -1;
1202 p->tex_Texture_ScreenDiffuse = -1;
1203 p->tex_Texture_ScreenSpecular = -1;
1204 p->tex_Texture_ReflectMask = -1;
1205 p->tex_Texture_ReflectCube = -1;
1206 p->tex_Texture_BounceGrid = -1;
1208 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1209 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1210 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1211 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1212 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1213 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1214 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1215 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1216 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1217 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1218 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1219 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1220 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1221 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1222 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1223 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1224 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1225 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1226 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1227 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1228 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1229 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1230 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1231 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1232 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1233 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1234 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1235 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1236 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1237 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1239 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1242 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1246 Mem_Free(vertexstring);
1248 Mem_Free(geometrystring);
1250 Mem_Free(fragmentstring);
1253 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1255 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1256 if (r_glsl_permutation != perm)
1258 r_glsl_permutation = perm;
1259 if (!r_glsl_permutation->program)
1261 if (!r_glsl_permutation->compiled)
1262 R_GLSL_CompilePermutation(perm, mode, permutation);
1263 if (!r_glsl_permutation->program)
1265 // remove features until we find a valid permutation
1267 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1269 // reduce i more quickly whenever it would not remove any bits
1270 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1271 if (!(permutation & j))
1274 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1275 if (!r_glsl_permutation->compiled)
1276 R_GLSL_CompilePermutation(perm, mode, permutation);
1277 if (r_glsl_permutation->program)
1280 if (i >= SHADERPERMUTATION_COUNT)
1282 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1283 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1284 qglUseProgram(0);CHECKGLERROR
1285 return; // no bit left to clear, entire mode is broken
1290 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1292 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1293 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1294 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1301 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1302 extern D3DCAPS9 vid_d3d9caps;
1305 struct r_hlsl_permutation_s;
1306 typedef struct r_hlsl_permutation_s
1308 /// hash lookup data
1309 struct r_hlsl_permutation_s *hashnext;
1311 unsigned int permutation;
1313 /// indicates if we have tried compiling this permutation already
1315 /// NULL if compilation failed
1316 IDirect3DVertexShader9 *vertexshader;
1317 IDirect3DPixelShader9 *pixelshader;
1319 r_hlsl_permutation_t;
1321 typedef enum D3DVSREGISTER_e
1323 D3DVSREGISTER_TexMatrix = 0, // float4x4
1324 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1325 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1326 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1327 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1328 D3DVSREGISTER_ModelToLight = 20, // float4x4
1329 D3DVSREGISTER_EyePosition = 24,
1330 D3DVSREGISTER_FogPlane = 25,
1331 D3DVSREGISTER_LightDir = 26,
1332 D3DVSREGISTER_LightPosition = 27,
1336 typedef enum D3DPSREGISTER_e
1338 D3DPSREGISTER_Alpha = 0,
1339 D3DPSREGISTER_BloomBlur_Parameters = 1,
1340 D3DPSREGISTER_ClientTime = 2,
1341 D3DPSREGISTER_Color_Ambient = 3,
1342 D3DPSREGISTER_Color_Diffuse = 4,
1343 D3DPSREGISTER_Color_Specular = 5,
1344 D3DPSREGISTER_Color_Glow = 6,
1345 D3DPSREGISTER_Color_Pants = 7,
1346 D3DPSREGISTER_Color_Shirt = 8,
1347 D3DPSREGISTER_DeferredColor_Ambient = 9,
1348 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1349 D3DPSREGISTER_DeferredColor_Specular = 11,
1350 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1351 D3DPSREGISTER_DeferredMod_Specular = 13,
1352 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1353 D3DPSREGISTER_EyePosition = 15, // unused
1354 D3DPSREGISTER_FogColor = 16,
1355 D3DPSREGISTER_FogHeightFade = 17,
1356 D3DPSREGISTER_FogPlane = 18,
1357 D3DPSREGISTER_FogPlaneViewDist = 19,
1358 D3DPSREGISTER_FogRangeRecip = 20,
1359 D3DPSREGISTER_LightColor = 21,
1360 D3DPSREGISTER_LightDir = 22, // unused
1361 D3DPSREGISTER_LightPosition = 23,
1362 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1363 D3DPSREGISTER_PixelSize = 25,
1364 D3DPSREGISTER_ReflectColor = 26,
1365 D3DPSREGISTER_ReflectFactor = 27,
1366 D3DPSREGISTER_ReflectOffset = 28,
1367 D3DPSREGISTER_RefractColor = 29,
1368 D3DPSREGISTER_Saturation = 30,
1369 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1370 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1371 D3DPSREGISTER_ScreenToDepth = 33,
1372 D3DPSREGISTER_ShadowMap_Parameters = 34,
1373 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1374 D3DPSREGISTER_SpecularPower = 36,
1375 D3DPSREGISTER_UserVec1 = 37,
1376 D3DPSREGISTER_UserVec2 = 38,
1377 D3DPSREGISTER_UserVec3 = 39,
1378 D3DPSREGISTER_UserVec4 = 40,
1379 D3DPSREGISTER_ViewTintColor = 41,
1380 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1381 D3DPSREGISTER_BloomColorSubtract = 43,
1382 D3DPSREGISTER_ViewToLight = 44, // float4x4
1383 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1384 D3DPSREGISTER_NormalmapScrollBlend = 52,
1389 /// information about each possible shader permutation
1390 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1391 /// currently selected permutation
1392 r_hlsl_permutation_t *r_hlsl_permutation;
1393 /// storage for permutations linked in the hash table
1394 memexpandablearray_t r_hlsl_permutationarray;
1396 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1398 //unsigned int hashdepth = 0;
1399 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1400 r_hlsl_permutation_t *p;
1401 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1403 if (p->mode == mode && p->permutation == permutation)
1405 //if (hashdepth > 10)
1406 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1411 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1413 p->permutation = permutation;
1414 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1415 r_hlsl_permutationhash[mode][hashindex] = p;
1416 //if (hashdepth > 10)
1417 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1421 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1424 if (!filename || !filename[0])
1426 if (!strcmp(filename, "hlsl/default.hlsl"))
1428 if (!hlslshaderstring)
1430 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1431 if (hlslshaderstring)
1432 Con_DPrintf("Loading shaders from file %s...\n", filename);
1434 hlslshaderstring = (char *)builtinhlslshaderstring;
1436 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1437 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1438 return shaderstring;
1440 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1443 if (printfromdisknotice)
1444 Con_DPrintf("from disk %s... ", filename);
1445 return shaderstring;
1447 return shaderstring;
1451 //#include <d3dx9shader.h>
1452 //#include <d3dx9mesh.h>
1454 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1456 DWORD *vsbin = NULL;
1457 DWORD *psbin = NULL;
1458 fs_offset_t vsbinsize;
1459 fs_offset_t psbinsize;
1460 // IDirect3DVertexShader9 *vs = NULL;
1461 // IDirect3DPixelShader9 *ps = NULL;
1462 ID3DXBuffer *vslog = NULL;
1463 ID3DXBuffer *vsbuffer = NULL;
1464 ID3DXConstantTable *vsconstanttable = NULL;
1465 ID3DXBuffer *pslog = NULL;
1466 ID3DXBuffer *psbuffer = NULL;
1467 ID3DXConstantTable *psconstanttable = NULL;
1470 char temp[MAX_INPUTLINE];
1471 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1472 qboolean debugshader = gl_paranoid.integer != 0;
1473 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1477 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1478 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1480 if ((!vsbin && vertstring) || (!psbin && fragstring))
1482 const char* dllnames_d3dx9 [] =
1506 dllhandle_t d3dx9_dll = NULL;
1507 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1509 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1510 dllfunction_t d3dx9_dllfuncs[] =
1512 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1513 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1514 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1517 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1519 DWORD shaderflags = 0;
1521 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1522 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1523 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1524 if (vertstring && vertstring[0])
1528 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1529 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1530 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1531 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1534 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1537 vsbinsize = vsbuffer->GetBufferSize();
1538 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1539 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1540 vsbuffer->Release();
1544 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1545 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1549 if (fragstring && fragstring[0])
1553 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1554 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1555 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1556 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1559 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1562 psbinsize = psbuffer->GetBufferSize();
1563 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1564 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1565 psbuffer->Release();
1569 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1570 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1574 Sys_UnloadLibrary(&d3dx9_dll);
1577 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1581 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1582 if (FAILED(vsresult))
1583 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1584 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1585 if (FAILED(psresult))
1586 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1588 // free the shader data
1589 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1590 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1593 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1596 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1597 int vertstring_length = 0;
1598 int geomstring_length = 0;
1599 int fragstring_length = 0;
1601 char *vertexstring, *geometrystring, *fragmentstring;
1602 char *vertstring, *geomstring, *fragstring;
1603 char permutationname[256];
1604 char cachename[256];
1605 int vertstrings_count = 0;
1606 int geomstrings_count = 0;
1607 int fragstrings_count = 0;
1608 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1610 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1615 p->vertexshader = NULL;
1616 p->pixelshader = NULL;
1618 permutationname[0] = 0;
1620 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1621 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1622 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1624 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1625 strlcat(cachename, "hlsl/", sizeof(cachename));
1627 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1628 vertstrings_count = 0;
1629 geomstrings_count = 0;
1630 fragstrings_count = 0;
1631 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1632 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1633 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1635 // the first pretext is which type of shader to compile as
1636 // (later these will all be bound together as a program object)
1637 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1638 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1639 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1641 // the second pretext is the mode (for example a light source)
1642 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1643 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1644 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1645 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1646 strlcat(cachename, modeinfo->name, sizeof(cachename));
1648 // now add all the permutation pretexts
1649 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1651 if (permutation & (1<<i))
1653 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1654 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1655 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1656 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1657 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1661 // keep line numbers correct
1662 vertstrings_list[vertstrings_count++] = "\n";
1663 geomstrings_list[geomstrings_count++] = "\n";
1664 fragstrings_list[fragstrings_count++] = "\n";
1669 R_CompileShader_AddStaticParms(mode, permutation);
1670 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671 vertstrings_count += shaderstaticparms_count;
1672 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673 geomstrings_count += shaderstaticparms_count;
1674 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1675 fragstrings_count += shaderstaticparms_count;
1677 // replace spaces in the cachename with _ characters
1678 for (i = 0;cachename[i];i++)
1679 if (cachename[i] == ' ')
1682 // now append the shader text itself
1683 vertstrings_list[vertstrings_count++] = vertexstring;
1684 geomstrings_list[geomstrings_count++] = geometrystring;
1685 fragstrings_list[fragstrings_count++] = fragmentstring;
1687 // if any sources were NULL, clear the respective list
1689 vertstrings_count = 0;
1690 if (!geometrystring)
1691 geomstrings_count = 0;
1692 if (!fragmentstring)
1693 fragstrings_count = 0;
1695 vertstring_length = 0;
1696 for (i = 0;i < vertstrings_count;i++)
1697 vertstring_length += strlen(vertstrings_list[i]);
1698 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1699 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1700 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1702 geomstring_length = 0;
1703 for (i = 0;i < geomstrings_count;i++)
1704 geomstring_length += strlen(geomstrings_list[i]);
1705 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1706 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1707 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1709 fragstring_length = 0;
1710 for (i = 0;i < fragstrings_count;i++)
1711 fragstring_length += strlen(fragstrings_list[i]);
1712 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1713 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1714 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1716 // try to load the cached shader, or generate one
1717 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1719 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1720 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1722 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1726 Mem_Free(vertstring);
1728 Mem_Free(geomstring);
1730 Mem_Free(fragstring);
1732 Mem_Free(vertexstring);
1734 Mem_Free(geometrystring);
1736 Mem_Free(fragmentstring);
1739 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1740 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1741 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);}
1742 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);}
1743 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);}
1744 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);}
1746 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1753 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1755 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1756 if (r_hlsl_permutation != perm)
1758 r_hlsl_permutation = perm;
1759 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1761 if (!r_hlsl_permutation->compiled)
1762 R_HLSL_CompilePermutation(perm, mode, permutation);
1763 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1765 // remove features until we find a valid permutation
1767 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1769 // reduce i more quickly whenever it would not remove any bits
1770 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1771 if (!(permutation & j))
1774 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1775 if (!r_hlsl_permutation->compiled)
1776 R_HLSL_CompilePermutation(perm, mode, permutation);
1777 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1780 if (i >= SHADERPERMUTATION_COUNT)
1782 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1783 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784 return; // no bit left to clear, entire mode is broken
1788 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1789 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1791 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1792 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1793 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1797 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1799 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1800 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1801 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1802 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1805 void R_GLSL_Restart_f(void)
1807 unsigned int i, limit;
1808 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1809 Mem_Free(glslshaderstring);
1810 glslshaderstring = NULL;
1811 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1812 Mem_Free(hlslshaderstring);
1813 hlslshaderstring = NULL;
1814 switch(vid.renderpath)
1816 case RENDERPATH_D3D9:
1819 r_hlsl_permutation_t *p;
1820 r_hlsl_permutation = NULL;
1821 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1822 for (i = 0;i < limit;i++)
1824 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1826 if (p->vertexshader)
1827 IDirect3DVertexShader9_Release(p->vertexshader);
1829 IDirect3DPixelShader9_Release(p->pixelshader);
1830 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1833 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1837 case RENDERPATH_D3D10:
1838 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840 case RENDERPATH_D3D11:
1841 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1843 case RENDERPATH_GL20:
1844 case RENDERPATH_GLES2:
1846 r_glsl_permutation_t *p;
1847 r_glsl_permutation = NULL;
1848 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1849 for (i = 0;i < limit;i++)
1851 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1853 GL_Backend_FreeProgram(p->program);
1854 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1857 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1860 case RENDERPATH_GL11:
1861 case RENDERPATH_GL13:
1862 case RENDERPATH_GLES1:
1864 case RENDERPATH_SOFT:
1869 void R_GLSL_DumpShader_f(void)
1874 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1877 FS_Print(file, "/* The engine may define the following macros:\n");
1878 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1879 for (i = 0;i < SHADERMODE_COUNT;i++)
1880 FS_Print(file, glslshadermodeinfo[i].pretext);
1881 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1882 FS_Print(file, shaderpermutationinfo[i].pretext);
1883 FS_Print(file, "*/\n");
1884 FS_Print(file, builtinshaderstring);
1886 Con_Printf("glsl/default.glsl written\n");
1889 Con_Printf("failed to write to glsl/default.glsl\n");
1891 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1894 FS_Print(file, "/* The engine may define the following macros:\n");
1895 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1896 for (i = 0;i < SHADERMODE_COUNT;i++)
1897 FS_Print(file, hlslshadermodeinfo[i].pretext);
1898 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1899 FS_Print(file, shaderpermutationinfo[i].pretext);
1900 FS_Print(file, "*/\n");
1901 FS_Print(file, builtinhlslshaderstring);
1903 Con_Printf("hlsl/default.hlsl written\n");
1906 Con_Printf("failed to write to hlsl/default.hlsl\n");
1909 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1912 texturemode = GL_MODULATE;
1913 switch (vid.renderpath)
1915 case RENDERPATH_D3D9:
1917 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1918 R_Mesh_TexBind(GL20TU_FIRST , first );
1919 R_Mesh_TexBind(GL20TU_SECOND, second);
1922 case RENDERPATH_D3D10:
1923 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925 case RENDERPATH_D3D11:
1926 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928 case RENDERPATH_GL20:
1929 case RENDERPATH_GLES2:
1930 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1931 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1932 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1934 case RENDERPATH_GL13:
1935 case RENDERPATH_GLES1:
1936 R_Mesh_TexBind(0, first );
1937 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1938 R_Mesh_TexBind(1, second);
1940 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1942 case RENDERPATH_GL11:
1943 R_Mesh_TexBind(0, first );
1945 case RENDERPATH_SOFT:
1946 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
1947 R_Mesh_TexBind(GL20TU_FIRST , first );
1948 R_Mesh_TexBind(GL20TU_SECOND, second);
1953 void R_SetupShader_DepthOrShadow(void)
1955 switch (vid.renderpath)
1957 case RENDERPATH_D3D9:
1959 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1962 case RENDERPATH_D3D10:
1963 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1965 case RENDERPATH_D3D11:
1966 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1968 case RENDERPATH_GL20:
1969 case RENDERPATH_GLES2:
1970 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1972 case RENDERPATH_GL13:
1973 case RENDERPATH_GLES1:
1974 R_Mesh_TexBind(0, 0);
1975 R_Mesh_TexBind(1, 0);
1977 case RENDERPATH_GL11:
1978 R_Mesh_TexBind(0, 0);
1980 case RENDERPATH_SOFT:
1981 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1986 void R_SetupShader_ShowDepth(void)
1988 switch (vid.renderpath)
1990 case RENDERPATH_D3D9:
1992 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1995 case RENDERPATH_D3D10:
1996 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998 case RENDERPATH_D3D11:
1999 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001 case RENDERPATH_GL20:
2002 case RENDERPATH_GLES2:
2003 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
2005 case RENDERPATH_GL13:
2006 case RENDERPATH_GLES1:
2008 case RENDERPATH_GL11:
2010 case RENDERPATH_SOFT:
2011 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2016 extern qboolean r_shadow_usingdeferredprepass;
2017 extern cvar_t r_shadow_deferred_8bitrange;
2018 extern rtexture_t *r_shadow_attenuationgradienttexture;
2019 extern rtexture_t *r_shadow_attenuation2dtexture;
2020 extern rtexture_t *r_shadow_attenuation3dtexture;
2021 extern qboolean r_shadow_usingshadowmap2d;
2022 extern qboolean r_shadow_usingshadowmaportho;
2023 extern float r_shadow_shadowmap_texturescale[2];
2024 extern float r_shadow_shadowmap_parameters[4];
2025 extern qboolean r_shadow_shadowmapvsdct;
2026 extern qboolean r_shadow_shadowmapsampler;
2027 extern int r_shadow_shadowmappcf;
2028 extern rtexture_t *r_shadow_shadowmap2dtexture;
2029 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2030 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2031 extern matrix4x4_t r_shadow_shadowmapmatrix;
2032 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2033 extern int r_shadow_prepass_width;
2034 extern int r_shadow_prepass_height;
2035 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2036 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2037 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2038 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2039 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2041 #define BLENDFUNC_ALLOWS_COLORMOD 1
2042 #define BLENDFUNC_ALLOWS_FOG 2
2043 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2044 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2045 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2046 static int R_BlendFuncFlags(int src, int dst)
2050 // a blendfunc allows colormod if:
2051 // a) it can never keep the destination pixel invariant, or
2052 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2053 // this is to prevent unintended side effects from colormod
2055 // a blendfunc allows fog if:
2056 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2057 // this is to prevent unintended side effects from fog
2059 // these checks are the output of fogeval.pl
2061 r |= BLENDFUNC_ALLOWS_COLORMOD;
2062 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2063 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2065 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2066 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2067 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2068 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2069 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2070 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2071 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2072 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2074 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2075 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2076 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2077 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2078 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2080 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2081 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2082 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
2089 // select a permutation of the lighting shader appropriate to this
2090 // combination of texture, entity, light source, and fogging, only use the
2091 // minimum features necessary to avoid wasting rendering time in the
2092 // fragment shader on features that are not being used
2093 unsigned int permutation = 0;
2094 unsigned int mode = 0;
2096 static float dummy_colormod[3] = {1, 1, 1};
2097 float *colormod = rsurface.colormod;
2099 matrix4x4_t tempmatrix;
2100 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2101 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2102 permutation |= SHADERPERMUTATION_ALPHAKILL;
2103 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2104 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2105 if (rsurfacepass == RSURFPASS_BACKGROUND)
2107 // distorted background
2108 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2110 mode = SHADERMODE_WATER;
2111 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2113 // this is the right thing to do for wateralpha
2114 GL_BlendFunc(GL_ONE, GL_ZERO);
2115 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2119 // this is the right thing to do for entity alpha
2120 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2121 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2124 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2126 mode = SHADERMODE_REFRACTION;
2127 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2128 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2132 mode = SHADERMODE_GENERIC;
2133 permutation |= SHADERPERMUTATION_DIFFUSE;
2134 GL_BlendFunc(GL_ONE, GL_ZERO);
2135 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2138 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2140 if (r_glsl_offsetmapping.integer)
2142 switch(rsurface.texture->offsetmapping)
2144 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2145 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2146 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2147 case OFFSETMAPPING_OFF: break;
2150 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2151 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2152 // normalmap (deferred prepass), may use alpha test on diffuse
2153 mode = SHADERMODE_DEFERREDGEOMETRY;
2154 GL_BlendFunc(GL_ONE, GL_ZERO);
2155 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2157 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2159 if (r_glsl_offsetmapping.integer)
2161 switch(rsurface.texture->offsetmapping)
2163 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166 case OFFSETMAPPING_OFF: break;
2169 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172 mode = SHADERMODE_LIGHTSOURCE;
2173 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2174 permutation |= SHADERPERMUTATION_CUBEFILTER;
2175 if (diffusescale > 0)
2176 permutation |= SHADERPERMUTATION_DIFFUSE;
2177 if (specularscale > 0)
2178 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2179 if (r_refdef.fogenabled)
2180 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2181 if (rsurface.texture->colormapping)
2182 permutation |= SHADERPERMUTATION_COLORMAPPING;
2183 if (r_shadow_usingshadowmap2d)
2185 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2186 if(r_shadow_shadowmapvsdct)
2187 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2189 if (r_shadow_shadowmapsampler)
2190 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2191 if (r_shadow_shadowmappcf > 1)
2192 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2193 else if (r_shadow_shadowmappcf)
2194 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2196 if (rsurface.texture->reflectmasktexture)
2197 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2198 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2199 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2201 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2203 if (r_glsl_offsetmapping.integer)
2205 switch(rsurface.texture->offsetmapping)
2207 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2208 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2209 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210 case OFFSETMAPPING_OFF: break;
2213 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2214 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2215 // unshaded geometry (fullbright or ambient model lighting)
2216 mode = SHADERMODE_FLATCOLOR;
2217 ambientscale = diffusescale = specularscale = 0;
2218 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2219 permutation |= SHADERPERMUTATION_GLOW;
2220 if (r_refdef.fogenabled)
2221 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2222 if (rsurface.texture->colormapping)
2223 permutation |= SHADERPERMUTATION_COLORMAPPING;
2224 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2226 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2227 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2229 if (r_shadow_shadowmapsampler)
2230 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2231 if (r_shadow_shadowmappcf > 1)
2232 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2233 else if (r_shadow_shadowmappcf)
2234 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2237 permutation |= SHADERPERMUTATION_REFLECTION;
2238 if (rsurface.texture->reflectmasktexture)
2239 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2240 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2241 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2243 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2245 if (r_glsl_offsetmapping.integer)
2247 switch(rsurface.texture->offsetmapping)
2249 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2250 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2251 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2252 case OFFSETMAPPING_OFF: break;
2255 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2256 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2257 // directional model lighting
2258 mode = SHADERMODE_LIGHTDIRECTION;
2259 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2260 permutation |= SHADERPERMUTATION_GLOW;
2261 permutation |= SHADERPERMUTATION_DIFFUSE;
2262 if (specularscale > 0)
2263 permutation |= SHADERPERMUTATION_SPECULAR;
2264 if (r_refdef.fogenabled)
2265 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2266 if (rsurface.texture->colormapping)
2267 permutation |= SHADERPERMUTATION_COLORMAPPING;
2268 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2270 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2271 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2273 if (r_shadow_shadowmapsampler)
2274 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2275 if (r_shadow_shadowmappcf > 1)
2276 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2277 else if (r_shadow_shadowmappcf)
2278 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2280 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2281 permutation |= SHADERPERMUTATION_REFLECTION;
2282 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2283 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2284 if (rsurface.texture->reflectmasktexture)
2285 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2286 if (r_shadow_bouncegridtexture)
2288 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2289 if (r_shadow_bouncegriddirectional)
2290 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2292 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2297 if (r_glsl_offsetmapping.integer)
2299 switch(rsurface.texture->offsetmapping)
2301 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2302 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2303 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2304 case OFFSETMAPPING_OFF: break;
2307 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2308 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2309 // ambient model lighting
2310 mode = SHADERMODE_LIGHTDIRECTION;
2311 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2312 permutation |= SHADERPERMUTATION_GLOW;
2313 if (r_refdef.fogenabled)
2314 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315 if (rsurface.texture->colormapping)
2316 permutation |= SHADERPERMUTATION_COLORMAPPING;
2317 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2319 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2322 if (r_shadow_shadowmapsampler)
2323 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324 if (r_shadow_shadowmappcf > 1)
2325 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326 else if (r_shadow_shadowmappcf)
2327 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2329 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330 permutation |= SHADERPERMUTATION_REFLECTION;
2331 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333 if (rsurface.texture->reflectmasktexture)
2334 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335 if (r_shadow_bouncegridtexture)
2337 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338 if (r_shadow_bouncegriddirectional)
2339 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2341 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346 if (r_glsl_offsetmapping.integer)
2348 switch(rsurface.texture->offsetmapping)
2350 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2351 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353 case OFFSETMAPPING_OFF: break;
2356 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2357 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2359 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360 permutation |= SHADERPERMUTATION_GLOW;
2361 if (r_refdef.fogenabled)
2362 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2363 if (rsurface.texture->colormapping)
2364 permutation |= SHADERPERMUTATION_COLORMAPPING;
2365 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2367 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2368 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2370 if (r_shadow_shadowmapsampler)
2371 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2372 if (r_shadow_shadowmappcf > 1)
2373 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2374 else if (r_shadow_shadowmappcf)
2375 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2377 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378 permutation |= SHADERPERMUTATION_REFLECTION;
2379 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2380 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381 if (rsurface.texture->reflectmasktexture)
2382 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383 if (FAKELIGHT_ENABLED)
2385 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2386 mode = SHADERMODE_FAKELIGHT;
2387 permutation |= SHADERPERMUTATION_DIFFUSE;
2388 if (specularscale > 0)
2389 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2391 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2393 // deluxemapping (light direction texture)
2394 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2395 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2397 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398 permutation |= SHADERPERMUTATION_DIFFUSE;
2399 if (specularscale > 0)
2400 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2404 // fake deluxemapping (uniform light direction in tangentspace)
2405 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2406 permutation |= SHADERPERMUTATION_DIFFUSE;
2407 if (specularscale > 0)
2408 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2410 else if (rsurface.uselightmaptexture)
2412 // ordinary lightmapping (q1bsp, q3bsp)
2413 mode = SHADERMODE_LIGHTMAP;
2417 // ordinary vertex coloring (q3bsp)
2418 mode = SHADERMODE_VERTEXCOLOR;
2420 if (r_shadow_bouncegridtexture)
2422 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2423 if (r_shadow_bouncegriddirectional)
2424 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2426 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2427 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2429 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2430 colormod = dummy_colormod;
2431 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2432 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2433 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2434 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2435 switch(vid.renderpath)
2437 case RENDERPATH_D3D9:
2439 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), texturenumsurfaces, texturesurfacelist);
2440 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2441 R_SetupShader_SetPermutationHLSL(mode, permutation);
2442 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2443 if (mode == SHADERMODE_LIGHTSOURCE)
2445 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2446 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2450 if (mode == SHADERMODE_LIGHTDIRECTION)
2452 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2455 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2456 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2457 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2458 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2459 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2461 if (mode == SHADERMODE_LIGHTSOURCE)
2463 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2464 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2465 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2466 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2467 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2469 // additive passes are only darkened by fog, not tinted
2470 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2471 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2475 if (mode == SHADERMODE_FLATCOLOR)
2477 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2479 else if (mode == SHADERMODE_LIGHTDIRECTION)
2481 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2482 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2483 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2484 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2485 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2486 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2487 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2491 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2492 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2493 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2494 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2495 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2497 // additive passes are only darkened by fog, not tinted
2498 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2499 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2501 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2502 hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2503 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2504 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2505 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2506 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2507 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2508 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2509 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2510 if (mode == SHADERMODE_WATER)
2511 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2513 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2514 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2516 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2517 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2518 if (rsurface.texture->pantstexture)
2519 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2521 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2522 if (rsurface.texture->shirttexture)
2523 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2525 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2526 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2528 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2529 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2530 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2531 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2532 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2533 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2534 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2536 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2537 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2539 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2540 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2541 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2542 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2543 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2544 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2545 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2546 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2547 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2548 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2549 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2550 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2551 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2552 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2553 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2554 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2555 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2556 if (rsurfacepass == RSURFPASS_BACKGROUND)
2558 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2559 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2560 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2564 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2566 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2567 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2568 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2569 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2570 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2572 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2573 if (rsurface.rtlight)
2575 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2576 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2581 case RENDERPATH_D3D10:
2582 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2584 case RENDERPATH_D3D11:
2585 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2587 case RENDERPATH_GL20:
2588 case RENDERPATH_GLES2:
2589 if (!vid.useinterleavedarrays)
2591 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), texturenumsurfaces, texturesurfacelist);
2592 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2593 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2594 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2595 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2596 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2597 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2598 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2602 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), texturenumsurfaces, texturesurfacelist);
2603 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2605 R_SetupShader_SetPermutationGLSL(mode, permutation);
2606 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2607 if (mode == SHADERMODE_LIGHTSOURCE)
2609 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2610 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2611 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2612 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2613 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2614 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2616 // additive passes are only darkened by fog, not tinted
2617 if (r_glsl_permutation->loc_FogColor >= 0)
2618 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2619 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2623 if (mode == SHADERMODE_FLATCOLOR)
2625 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2627 else if (mode == SHADERMODE_LIGHTDIRECTION)
2629 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2630 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2631 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2632 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2633 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2634 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2635 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2639 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2640 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2641 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2642 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2643 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2645 // additive passes are only darkened by fog, not tinted
2646 if (r_glsl_permutation->loc_FogColor >= 0)
2648 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2649 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2651 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2653 if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2654 if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2655 if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2656 if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2657 if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2658 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2659 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2660 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2661 if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2663 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2664 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2665 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2666 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2667 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2669 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2670 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2671 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2672 if (r_glsl_permutation->loc_Color_Pants >= 0)
2674 if (rsurface.texture->pantstexture)
2675 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2677 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2679 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2681 if (rsurface.texture->shirttexture)
2682 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2684 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2686 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]);
2687 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2688 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2689 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2690 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2691 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2692 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2693 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2694 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2696 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]);
2697 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2698 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2699 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2701 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2702 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2703 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2704 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2705 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2706 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2707 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2708 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2709 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2710 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2711 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2712 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2713 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2714 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2715 if (r_glsl_permutation->tex_Texture_ReflectCube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2716 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2717 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2718 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2719 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2720 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2721 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723 if (r_glsl_permutation->tex_Texture_Refraction >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2724 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2725 if (r_glsl_permutation->tex_Texture_Reflection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2729 if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2731 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2732 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2733 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2734 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2735 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2737 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2738 if (rsurface.rtlight)
2740 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2741 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2744 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2747 case RENDERPATH_GL11:
2748 case RENDERPATH_GL13:
2749 case RENDERPATH_GLES1:
2751 case RENDERPATH_SOFT:
2752 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), texturenumsurfaces, texturesurfacelist);
2753 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2754 R_SetupShader_SetPermutationSoft(mode, permutation);
2755 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2756 if (mode == SHADERMODE_LIGHTSOURCE)
2758 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2762 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2765 // additive passes are only darkened by fog, not tinted
2766 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2767 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2771 if (mode == SHADERMODE_FLATCOLOR)
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2775 else if (mode == SHADERMODE_LIGHTDIRECTION)
2777 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2780 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2781 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2783 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2791 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2793 // additive passes are only darkened by fog, not tinted
2794 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2797 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2798 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2799 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2800 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2801 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2802 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2803 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2804 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2805 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2806 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2808 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2809 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2810 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2811 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2812 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2814 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2815 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2816 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2817 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2819 if (rsurface.texture->pantstexture)
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2822 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2824 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2826 if (rsurface.texture->shirttexture)
2827 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2829 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2831 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2832 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2833 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2834 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2835 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2836 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2837 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2838 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2839 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2841 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2842 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2844 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2845 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2846 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2847 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2848 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2849 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2850 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2851 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2852 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2853 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2854 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2855 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2856 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2857 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2858 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2859 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2860 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2861 if (rsurfacepass == RSURFPASS_BACKGROUND)
2863 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2864 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2865 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2869 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2871 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2872 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2873 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2874 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2875 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2877 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2878 if (rsurface.rtlight)
2880 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2881 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2888 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2890 // select a permutation of the lighting shader appropriate to this
2891 // combination of texture, entity, light source, and fogging, only use the
2892 // minimum features necessary to avoid wasting rendering time in the
2893 // fragment shader on features that are not being used
2894 unsigned int permutation = 0;
2895 unsigned int mode = 0;
2896 const float *lightcolorbase = rtlight->currentcolor;
2897 float ambientscale = rtlight->ambientscale;
2898 float diffusescale = rtlight->diffusescale;
2899 float specularscale = rtlight->specularscale;
2900 // this is the location of the light in view space
2901 vec3_t viewlightorigin;
2902 // this transforms from view space (camera) to light space (cubemap)
2903 matrix4x4_t viewtolight;
2904 matrix4x4_t lighttoview;
2905 float viewtolight16f[16];
2906 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2908 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2909 if (rtlight->currentcubemap != r_texture_whitecube)
2910 permutation |= SHADERPERMUTATION_CUBEFILTER;
2911 if (diffusescale > 0)
2912 permutation |= SHADERPERMUTATION_DIFFUSE;
2913 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2914 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2915 if (r_shadow_usingshadowmap2d)
2917 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2918 if (r_shadow_shadowmapvsdct)
2919 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2921 if (r_shadow_shadowmapsampler)
2922 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2923 if (r_shadow_shadowmappcf > 1)
2924 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2925 else if (r_shadow_shadowmappcf)
2926 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2928 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2929 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2930 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2931 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2932 switch(vid.renderpath)
2934 case RENDERPATH_D3D9:
2936 R_SetupShader_SetPermutationHLSL(mode, permutation);
2937 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2938 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2939 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2940 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2941 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2942 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2943 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2944 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2945 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2946 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2948 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2949 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2950 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2951 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2952 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2953 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2956 case RENDERPATH_D3D10:
2957 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2959 case RENDERPATH_D3D11:
2960 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2962 case RENDERPATH_GL20:
2963 case RENDERPATH_GLES2:
2964 R_SetupShader_SetPermutationGLSL(mode, permutation);
2965 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2966 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2967 if (r_glsl_permutation->loc_DeferredColor_Ambient >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2968 if (r_glsl_permutation->loc_DeferredColor_Diffuse >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2969 if (r_glsl_permutation->loc_DeferredColor_Specular >= 0) qglUniform3f( r_glsl_permutation->loc_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2970 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f( r_glsl_permutation->loc_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2971 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f( r_glsl_permutation->loc_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2972 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));
2973 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]);
2974 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2976 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2977 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2978 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2979 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2980 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2981 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2983 case RENDERPATH_GL11:
2984 case RENDERPATH_GL13:
2985 case RENDERPATH_GLES1:
2987 case RENDERPATH_SOFT:
2988 R_SetupShader_SetPermutationGLSL(mode, permutation);
2989 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2990 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2991 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2992 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2993 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2994 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2995 DPSOFTRAST_Uniform4f( DPSOFTRAST_UNIFORM_ShadowMap_Parameters , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2996 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));
2997 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2998 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3000 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
3001 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
3002 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
3003 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
3004 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
3005 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3010 #define SKINFRAME_HASH 1024
3014 int loadsequence; // incremented each level change
3015 memexpandablearray_t array;
3016 skinframe_t *hash[SKINFRAME_HASH];
3019 r_skinframe_t r_skinframe;
3021 void R_SkinFrame_PrepareForPurge(void)
3023 r_skinframe.loadsequence++;
3024 // wrap it without hitting zero
3025 if (r_skinframe.loadsequence >= 200)
3026 r_skinframe.loadsequence = 1;
3029 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3033 // mark the skinframe as used for the purging code
3034 skinframe->loadsequence = r_skinframe.loadsequence;
3037 void R_SkinFrame_Purge(void)
3041 for (i = 0;i < SKINFRAME_HASH;i++)
3043 for (s = r_skinframe.hash[i];s;s = s->next)
3045 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3047 if (s->merged == s->base)
3049 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3050 R_PurgeTexture(s->stain );s->stain = NULL;
3051 R_PurgeTexture(s->merged);s->merged = NULL;
3052 R_PurgeTexture(s->base );s->base = NULL;
3053 R_PurgeTexture(s->pants );s->pants = NULL;
3054 R_PurgeTexture(s->shirt );s->shirt = NULL;
3055 R_PurgeTexture(s->nmap );s->nmap = NULL;
3056 R_PurgeTexture(s->gloss );s->gloss = NULL;
3057 R_PurgeTexture(s->glow );s->glow = NULL;
3058 R_PurgeTexture(s->fog );s->fog = NULL;
3059 R_PurgeTexture(s->reflect);s->reflect = NULL;
3060 s->loadsequence = 0;
3066 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3068 char basename[MAX_QPATH];
3070 Image_StripImageExtension(name, basename, sizeof(basename));
3072 if( last == NULL ) {
3074 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3075 item = r_skinframe.hash[hashindex];
3080 // linearly search through the hash bucket
3081 for( ; item ; item = item->next ) {
3082 if( !strcmp( item->basename, basename ) ) {
3089 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3093 char basename[MAX_QPATH];
3095 Image_StripImageExtension(name, basename, sizeof(basename));
3097 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3098 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3099 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3103 rtexture_t *dyntexture;
3104 // check whether its a dynamic texture
3105 dyntexture = CL_GetDynTexture( basename );
3106 if (!add && !dyntexture)
3108 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3109 memset(item, 0, sizeof(*item));
3110 strlcpy(item->basename, basename, sizeof(item->basename));
3111 item->base = dyntexture; // either NULL or dyntexture handle
3112 item->textureflags = textureflags;
3113 item->comparewidth = comparewidth;
3114 item->compareheight = compareheight;
3115 item->comparecrc = comparecrc;
3116 item->next = r_skinframe.hash[hashindex];
3117 r_skinframe.hash[hashindex] = item;
3119 else if( item->base == NULL )
3121 rtexture_t *dyntexture;
3122 // check whether its a dynamic texture
3123 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3124 dyntexture = CL_GetDynTexture( basename );
3125 item->base = dyntexture; // either NULL or dyntexture handle
3128 R_SkinFrame_MarkUsed(item);
3132 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3134 unsigned long long avgcolor[5], wsum; \
3142 for(pix = 0; pix < cnt; ++pix) \
3145 for(comp = 0; comp < 3; ++comp) \
3147 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3150 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3152 for(comp = 0; comp < 3; ++comp) \
3153 avgcolor[comp] += getpixel * w; \
3156 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3157 avgcolor[4] += getpixel; \
3159 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3161 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3162 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3163 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3164 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3167 extern cvar_t gl_picmip;
3168 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3171 unsigned char *pixels;
3172 unsigned char *bumppixels;
3173 unsigned char *basepixels = NULL;
3174 int basepixels_width = 0;
3175 int basepixels_height = 0;
3176 skinframe_t *skinframe;
3177 rtexture_t *ddsbase = NULL;
3178 qboolean ddshasalpha = false;
3179 float ddsavgcolor[4];
3180 char basename[MAX_QPATH];
3181 int miplevel = R_PicmipForFlags(textureflags);
3182 int savemiplevel = miplevel;
3185 if (cls.state == ca_dedicated)
3188 // return an existing skinframe if already loaded
3189 // if loading of the first image fails, don't make a new skinframe as it
3190 // would cause all future lookups of this to be missing
3191 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3192 if (skinframe && skinframe->base)
3195 Image_StripImageExtension(name, basename, sizeof(basename));
3197 // check for DDS texture file first
3198 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3200 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3201 if (basepixels == NULL)
3205 // FIXME handle miplevel
3207 if (developer_loading.integer)
3208 Con_Printf("loading skin \"%s\"\n", name);
3210 // we've got some pixels to store, so really allocate this new texture now
3212 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3213 skinframe->stain = NULL;
3214 skinframe->merged = NULL;
3215 skinframe->base = NULL;
3216 skinframe->pants = NULL;
3217 skinframe->shirt = NULL;
3218 skinframe->nmap = NULL;
3219 skinframe->gloss = NULL;
3220 skinframe->glow = NULL;
3221 skinframe->fog = NULL;
3222 skinframe->reflect = NULL;
3223 skinframe->hasalpha = false;
3227 skinframe->base = ddsbase;
3228 skinframe->hasalpha = ddshasalpha;
3229 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3230 if (r_loadfog && skinframe->hasalpha)
3231 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3232 //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]);
3236 basepixels_width = image_width;
3237 basepixels_height = image_height;
3238 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3239 if (textureflags & TEXF_ALPHA)
3241 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3243 if (basepixels[j] < 255)
3245 skinframe->hasalpha = true;
3249 if (r_loadfog && skinframe->hasalpha)
3251 // has transparent pixels
3252 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3253 for (j = 0;j < image_width * image_height * 4;j += 4)
3258 pixels[j+3] = basepixels[j+3];
3260 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3264 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3265 //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]);
3266 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3267 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3268 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3269 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3274 mymiplevel = savemiplevel;
3275 if (r_loadnormalmap)
3276 skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3277 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3279 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3280 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3281 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3282 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3285 // _norm is the name used by tenebrae and has been adopted as standard
3286 if (r_loadnormalmap && skinframe->nmap == NULL)
3288 mymiplevel = savemiplevel;
3289 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3291 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3295 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3297 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3298 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3299 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3301 Mem_Free(bumppixels);
3303 else if (r_shadow_bumpscale_basetexture.value > 0)
3305 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3306 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3307 skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3310 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3311 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3314 // _luma is supported only for tenebrae compatibility
3315 // _glow is the preferred name
3316 mymiplevel = savemiplevel;
3317 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3319 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_glow.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3320 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3321 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3322 Mem_Free(pixels);pixels = NULL;
3325 mymiplevel = savemiplevel;
3326 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3328 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_gloss.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3329 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3330 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3335 mymiplevel = savemiplevel;
3336 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3338 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3339 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3340 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3345 mymiplevel = savemiplevel;
3346 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3348 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_diffuse.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3349 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3350 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3355 mymiplevel = savemiplevel;
3356 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3358 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, r_texture_sRGB_skin_reflect.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3359 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3360 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3366 Mem_Free(basepixels);
3371 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3372 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3375 unsigned char *temp1, *temp2;
3376 skinframe_t *skinframe;
3378 if (cls.state == ca_dedicated)
3381 // if already loaded just return it, otherwise make a new skinframe
3382 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3383 if (skinframe && skinframe->base)
3386 skinframe->stain = NULL;
3387 skinframe->merged = NULL;
3388 skinframe->base = NULL;
3389 skinframe->pants = NULL;
3390 skinframe->shirt = NULL;
3391 skinframe->nmap = NULL;
3392 skinframe->gloss = NULL;
3393 skinframe->glow = NULL;
3394 skinframe->fog = NULL;
3395 skinframe->reflect = NULL;
3396 skinframe->hasalpha = false;
3398 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3402 if (developer_loading.integer)
3403 Con_Printf("loading 32bit skin \"%s\"\n", name);
3405 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3407 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3408 temp2 = temp1 + width * height * 4;
3409 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3410 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3413 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3414 if (textureflags & TEXF_ALPHA)
3416 for (i = 3;i < width * height * 4;i += 4)
3418 if (skindata[i] < 255)
3420 skinframe->hasalpha = true;
3424 if (r_loadfog && skinframe->hasalpha)
3426 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3427 memcpy(fogpixels, skindata, width * height * 4);
3428 for (i = 0;i < width * height * 4;i += 4)
3429 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3430 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3431 Mem_Free(fogpixels);
3435 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3436 //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]);
3441 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3445 skinframe_t *skinframe;
3447 if (cls.state == ca_dedicated)
3450 // if already loaded just return it, otherwise make a new skinframe
3451 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3452 if (skinframe && skinframe->base)
3455 skinframe->stain = NULL;
3456 skinframe->merged = NULL;
3457 skinframe->base = NULL;
3458 skinframe->pants = NULL;
3459 skinframe->shirt = NULL;
3460 skinframe->nmap = NULL;
3461 skinframe->gloss = NULL;
3462 skinframe->glow = NULL;
3463 skinframe->fog = NULL;
3464 skinframe->reflect = NULL;
3465 skinframe->hasalpha = false;
3467 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3471 if (developer_loading.integer)
3472 Con_Printf("loading quake skin \"%s\"\n", name);
3474 // 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)
3475 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3476 memcpy(skinframe->qpixels, skindata, width*height);
3477 skinframe->qwidth = width;
3478 skinframe->qheight = height;
3481 for (i = 0;i < width * height;i++)
3482 featuresmask |= palette_featureflags[skindata[i]];
3484 skinframe->hasalpha = false;
3485 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3486 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3487 skinframe->qgeneratemerged = true;
3488 skinframe->qgeneratebase = skinframe->qhascolormapping;
3489 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3491 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3492 //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]);
3497 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3501 unsigned char *skindata;
3503 if (!skinframe->qpixels)
3506 if (!skinframe->qhascolormapping)
3507 colormapped = false;
3511 if (!skinframe->qgeneratebase)
3516 if (!skinframe->qgeneratemerged)
3520 width = skinframe->qwidth;
3521 height = skinframe->qheight;
3522 skindata = skinframe->qpixels;
3524 if (skinframe->qgeneratenmap)
3526 unsigned char *temp1, *temp2;
3527 skinframe->qgeneratenmap = false;
3528 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3529 temp2 = temp1 + width * height * 4;
3530 // use either a custom palette or the quake palette
3531 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3532 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3533 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3537 if (skinframe->qgenerateglow)
3539 skinframe->qgenerateglow = false;
3540 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3545 skinframe->qgeneratebase = false;
3546 skinframe->base = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3547 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3548 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3552 skinframe->qgeneratemerged = false;
3553 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3556 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3558 Mem_Free(skinframe->qpixels);
3559 skinframe->qpixels = NULL;
3563 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)
3566 skinframe_t *skinframe;
3568 if (cls.state == ca_dedicated)
3571 // if already loaded just return it, otherwise make a new skinframe
3572 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3573 if (skinframe && skinframe->base)
3576 skinframe->stain = NULL;
3577 skinframe->merged = NULL;
3578 skinframe->base = NULL;
3579 skinframe->pants = NULL;
3580 skinframe->shirt = NULL;
3581 skinframe->nmap = NULL;
3582 skinframe->gloss = NULL;
3583 skinframe->glow = NULL;
3584 skinframe->fog = NULL;
3585 skinframe->reflect = NULL;
3586 skinframe->hasalpha = false;
3588 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3592 if (developer_loading.integer)
3593 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3595 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3596 if (textureflags & TEXF_ALPHA)
3598 for (i = 0;i < width * height;i++)
3600 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3602 skinframe->hasalpha = true;
3606 if (r_loadfog && skinframe->hasalpha)
3607 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3610 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3611 //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]);
3616 skinframe_t *R_SkinFrame_LoadMissing(void)
3618 skinframe_t *skinframe;
3620 if (cls.state == ca_dedicated)
3623 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3624 skinframe->stain = NULL;
3625 skinframe->merged = NULL;
3626 skinframe->base = NULL;
3627 skinframe->pants = NULL;
3628 skinframe->shirt = NULL;
3629 skinframe->nmap = NULL;
3630 skinframe->gloss = NULL;
3631 skinframe->glow = NULL;
3632 skinframe->fog = NULL;
3633 skinframe->reflect = NULL;
3634 skinframe->hasalpha = false;
3636 skinframe->avgcolor[0] = rand() / RAND_MAX;
3637 skinframe->avgcolor[1] = rand() / RAND_MAX;
3638 skinframe->avgcolor[2] = rand() / RAND_MAX;
3639 skinframe->avgcolor[3] = 1;
3644 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3645 typedef struct suffixinfo_s
3648 qboolean flipx, flipy, flipdiagonal;
3651 static suffixinfo_t suffix[3][6] =
3654 {"px", false, false, false},
3655 {"nx", false, false, false},
3656 {"py", false, false, false},
3657 {"ny", false, false, false},
3658 {"pz", false, false, false},
3659 {"nz", false, false, false}
3662 {"posx", false, false, false},
3663 {"negx", false, false, false},
3664 {"posy", false, false, false},
3665 {"negy", false, false, false},
3666 {"posz", false, false, false},
3667 {"negz", false, false, false}
3670 {"rt", true, false, true},
3671 {"lf", false, true, true},
3672 {"ft", true, true, false},
3673 {"bk", false, false, false},
3674 {"up", true, false, true},
3675 {"dn", true, false, true}
3679 static int componentorder[4] = {0, 1, 2, 3};
3681 rtexture_t *R_LoadCubemap(const char *basename)
3683 int i, j, cubemapsize;
3684 unsigned char *cubemappixels, *image_buffer;
3685 rtexture_t *cubemaptexture;
3687 // must start 0 so the first loadimagepixels has no requested width/height
3689 cubemappixels = NULL;
3690 cubemaptexture = NULL;
3691 // keep trying different suffix groups (posx, px, rt) until one loads
3692 for (j = 0;j < 3 && !cubemappixels;j++)
3694 // load the 6 images in the suffix group
3695 for (i = 0;i < 6;i++)
3697 // generate an image name based on the base and and suffix
3698 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3700 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3702 // an image loaded, make sure width and height are equal
3703 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3705 // if this is the first image to load successfully, allocate the cubemap memory
3706 if (!cubemappixels && image_width >= 1)
3708 cubemapsize = image_width;
3709 // note this clears to black, so unavailable sides are black
3710 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3712 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3714 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);
3717 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3719 Mem_Free(image_buffer);
3723 // if a cubemap loaded, upload it
3726 if (developer_loading.integer)
3727 Con_Printf("loading cubemap \"%s\"\n", basename);
3729 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3730 Mem_Free(cubemappixels);
3734 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3735 if (developer_loading.integer)
3737 Con_Printf("(tried tried images ");
3738 for (j = 0;j < 3;j++)
3739 for (i = 0;i < 6;i++)
3740 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3741 Con_Print(" and was unable to find any of them).\n");
3744 return cubemaptexture;
3747 rtexture_t *R_GetCubemap(const char *basename)
3750 for (i = 0;i < r_texture_numcubemaps;i++)
3751 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3752 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3753 if (i >= MAX_CUBEMAPS)
3754 return r_texture_whitecube;
3755 r_texture_numcubemaps++;
3756 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3757 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3758 return r_texture_cubemaps[i].texture;
3761 void R_FreeCubemaps(void)
3764 for (i = 0;i < r_texture_numcubemaps;i++)
3766 if (developer_loading.integer)
3767 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3768 if (r_texture_cubemaps[i].texture)
3769 R_FreeTexture(r_texture_cubemaps[i].texture);
3771 r_texture_numcubemaps = 0;
3774 void R_Main_FreeViewCache(void)
3776 if (r_refdef.viewcache.entityvisible)
3777 Mem_Free(r_refdef.viewcache.entityvisible);
3778 if (r_refdef.viewcache.world_pvsbits)
3779 Mem_Free(r_refdef.viewcache.world_pvsbits);
3780 if (r_refdef.viewcache.world_leafvisible)
3781 Mem_Free(r_refdef.viewcache.world_leafvisible);
3782 if (r_refdef.viewcache.world_surfacevisible)
3783 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3784 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3787 void R_Main_ResizeViewCache(void)
3789 int numentities = r_refdef.scene.numentities;
3790 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3791 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3792 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3793 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3794 if (r_refdef.viewcache.maxentities < numentities)
3796 r_refdef.viewcache.maxentities = numentities;
3797 if (r_refdef.viewcache.entityvisible)
3798 Mem_Free(r_refdef.viewcache.entityvisible);
3799 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3801 if (r_refdef.viewcache.world_numclusters != numclusters)
3803 r_refdef.viewcache.world_numclusters = numclusters;
3804 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3805 if (r_refdef.viewcache.world_pvsbits)
3806 Mem_Free(r_refdef.viewcache.world_pvsbits);
3807 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3809 if (r_refdef.viewcache.world_numleafs != numleafs)
3811 r_refdef.viewcache.world_numleafs = numleafs;
3812 if (r_refdef.viewcache.world_leafvisible)
3813 Mem_Free(r_refdef.viewcache.world_leafvisible);
3814 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3816 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3818 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3819 if (r_refdef.viewcache.world_surfacevisible)
3820 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3821 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3825 extern rtexture_t *loadingscreentexture;
3826 void gl_main_start(void)
3828 loadingscreentexture = NULL;
3829 r_texture_blanknormalmap = NULL;
3830 r_texture_white = NULL;
3831 r_texture_grey128 = NULL;
3832 r_texture_black = NULL;
3833 r_texture_whitecube = NULL;
3834 r_texture_normalizationcube = NULL;
3835 r_texture_fogattenuation = NULL;
3836 r_texture_fogheighttexture = NULL;
3837 r_texture_gammaramps = NULL;
3838 r_texture_numcubemaps = 0;
3840 r_loaddds = r_texture_dds_load.integer != 0;
3841 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3843 switch(vid.renderpath)
3845 case RENDERPATH_GL20:
3846 case RENDERPATH_D3D9:
3847 case RENDERPATH_D3D10:
3848 case RENDERPATH_D3D11:
3849 case RENDERPATH_SOFT:
3850 case RENDERPATH_GLES2:
3851 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3852 Cvar_SetValueQuick(&gl_combine, 1);
3853 Cvar_SetValueQuick(&r_glsl, 1);
3854 r_loadnormalmap = true;
3858 case RENDERPATH_GL13:
3859 case RENDERPATH_GLES1:
3860 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3861 Cvar_SetValueQuick(&gl_combine, 1);
3862 Cvar_SetValueQuick(&r_glsl, 0);
3863 r_loadnormalmap = false;
3864 r_loadgloss = false;
3867 case RENDERPATH_GL11:
3868 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3869 Cvar_SetValueQuick(&gl_combine, 0);
3870 Cvar_SetValueQuick(&r_glsl, 0);
3871 r_loadnormalmap = false;
3872 r_loadgloss = false;
3878 R_FrameData_Reset();
3882 memset(r_queries, 0, sizeof(r_queries));
3884 r_qwskincache = NULL;
3885 r_qwskincache_size = 0;
3887 // due to caching of texture_t references, the collision cache must be reset
3888 Collision_Cache_Reset(true);
3890 // set up r_skinframe loading system for textures
3891 memset(&r_skinframe, 0, sizeof(r_skinframe));
3892 r_skinframe.loadsequence = 1;
3893 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3895 r_main_texturepool = R_AllocTexturePool();
3896 R_BuildBlankTextures();
3898 if (vid.support.arb_texture_cube_map)
3901 R_BuildNormalizationCube();
3903 r_texture_fogattenuation = NULL;
3904 r_texture_fogheighttexture = NULL;
3905 r_texture_gammaramps = NULL;
3906 //r_texture_fogintensity = NULL;
3907 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3908 memset(&r_waterstate, 0, sizeof(r_waterstate));
3909 r_glsl_permutation = NULL;
3910 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3911 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3912 glslshaderstring = NULL;
3914 r_hlsl_permutation = NULL;
3915 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3916 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3918 hlslshaderstring = NULL;
3919 memset(&r_svbsp, 0, sizeof (r_svbsp));
3921 r_refdef.fogmasktable_density = 0;
3924 void gl_main_shutdown(void)
3927 R_FrameData_Reset();
3929 R_Main_FreeViewCache();
3931 switch(vid.renderpath)
3933 case RENDERPATH_GL11:
3934 case RENDERPATH_GL13:
3935 case RENDERPATH_GL20:
3936 case RENDERPATH_GLES1:
3937 case RENDERPATH_GLES2:
3939 qglDeleteQueriesARB(r_maxqueries, r_queries);
3941 case RENDERPATH_D3D9:
3942 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3944 case RENDERPATH_D3D10:
3945 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3947 case RENDERPATH_D3D11:
3948 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3950 case RENDERPATH_SOFT:
3956 memset(r_queries, 0, sizeof(r_queries));
3958 r_qwskincache = NULL;
3959 r_qwskincache_size = 0;
3961 // clear out the r_skinframe state
3962 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3963 memset(&r_skinframe, 0, sizeof(r_skinframe));
3966 Mem_Free(r_svbsp.nodes);
3967 memset(&r_svbsp, 0, sizeof (r_svbsp));
3968 R_FreeTexturePool(&r_main_texturepool);
3969 loadingscreentexture = NULL;
3970 r_texture_blanknormalmap = NULL;
3971 r_texture_white = NULL;
3972 r_texture_grey128 = NULL;
3973 r_texture_black = NULL;
3974 r_texture_whitecube = NULL;
3975 r_texture_normalizationcube = NULL;
3976 r_texture_fogattenuation = NULL;
3977 r_texture_fogheighttexture = NULL;
3978 r_texture_gammaramps = NULL;
3979 r_texture_numcubemaps = 0;
3980 //r_texture_fogintensity = NULL;
3981 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3982 memset(&r_waterstate, 0, sizeof(r_waterstate));
3985 r_glsl_permutation = NULL;
3986 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3987 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3988 glslshaderstring = NULL;
3990 r_hlsl_permutation = NULL;
3991 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3992 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3994 hlslshaderstring = NULL;
3997 extern void CL_ParseEntityLump(char *entitystring);
3998 void gl_main_newmap(void)
4000 // FIXME: move this code to client
4001 char *entities, entname[MAX_QPATH];
4003 Mem_Free(r_qwskincache);
4004 r_qwskincache = NULL;
4005 r_qwskincache_size = 0;
4008 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4009 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4011 CL_ParseEntityLump(entities);
4015 if (cl.worldmodel->brush.entities)
4016 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4018 R_Main_FreeViewCache();
4020 R_FrameData_Reset();
4023 void GL_Main_Init(void)
4025 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4027 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4028 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4029 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4030 if (gamemode == GAME_NEHAHRA)
4032 Cvar_RegisterVariable (&gl_fogenable);
4033 Cvar_RegisterVariable (&gl_fogdensity);
4034 Cvar_RegisterVariable (&gl_fogred);
4035 Cvar_RegisterVariable (&gl_foggreen);
4036 Cvar_RegisterVariable (&gl_fogblue);
4037 Cvar_RegisterVariable (&gl_fogstart);
4038 Cvar_RegisterVariable (&gl_fogend);
4039 Cvar_RegisterVariable (&gl_skyclip);
4041 Cvar_RegisterVariable(&r_motionblur);
4042 Cvar_RegisterVariable(&r_motionblur_maxblur);
4043 Cvar_RegisterVariable(&r_motionblur_bmin);
4044 Cvar_RegisterVariable(&r_motionblur_vmin);
4045 Cvar_RegisterVariable(&r_motionblur_vmax);
4046 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4047 Cvar_RegisterVariable(&r_motionblur_randomize);
4048 Cvar_RegisterVariable(&r_damageblur);
4049 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4050 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4051 Cvar_RegisterVariable(&r_equalize_entities_by);
4052 Cvar_RegisterVariable(&r_equalize_entities_to);
4053 Cvar_RegisterVariable(&r_depthfirst);
4054 Cvar_RegisterVariable(&r_useinfinitefarclip);
4055 Cvar_RegisterVariable(&r_farclip_base);
4056 Cvar_RegisterVariable(&r_farclip_world);
4057 Cvar_RegisterVariable(&r_nearclip);
4058 Cvar_RegisterVariable(&r_deformvertexes);
4059 Cvar_RegisterVariable(&r_transparent);
4060 Cvar_RegisterVariable(&r_showoverdraw);
4061 Cvar_RegisterVariable(&r_showbboxes);
4062 Cvar_RegisterVariable(&r_showsurfaces);
4063 Cvar_RegisterVariable(&r_showtris);
4064 Cvar_RegisterVariable(&r_shownormals);
4065 Cvar_RegisterVariable(&r_showlighting);
4066 Cvar_RegisterVariable(&r_showshadowvolumes);
4067 Cvar_RegisterVariable(&r_showcollisionbrushes);
4068 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4069 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4070 Cvar_RegisterVariable(&r_showdisabledepthtest);
4071 Cvar_RegisterVariable(&r_drawportals);
4072 Cvar_RegisterVariable(&r_drawentities);
4073 Cvar_RegisterVariable(&r_draw2d);
4074 Cvar_RegisterVariable(&r_drawworld);
4075 Cvar_RegisterVariable(&r_cullentities_trace);
4076 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4077 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4078 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4079 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4080 Cvar_RegisterVariable(&r_drawviewmodel);
4081 Cvar_RegisterVariable(&r_drawexteriormodel);
4082 Cvar_RegisterVariable(&r_speeds);
4083 Cvar_RegisterVariable(&r_fullbrights);
4084 Cvar_RegisterVariable(&r_wateralpha);
4085 Cvar_RegisterVariable(&r_dynamic);
4086 Cvar_RegisterVariable(&r_fakelight);
4087 Cvar_RegisterVariable(&r_fakelight_intensity);
4088 Cvar_RegisterVariable(&r_fullbright);
4089 Cvar_RegisterVariable(&r_shadows);
4090 Cvar_RegisterVariable(&r_shadows_darken);
4091 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4092 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4093 Cvar_RegisterVariable(&r_shadows_throwdistance);
4094 Cvar_RegisterVariable(&r_shadows_throwdirection);
4095 Cvar_RegisterVariable(&r_shadows_focus);
4096 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4097 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4098 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4099 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4100 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4101 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4102 Cvar_RegisterVariable(&r_fog_exp2);
4103 Cvar_RegisterVariable(&r_fog_clear);
4104 Cvar_RegisterVariable(&r_drawfog);
4105 Cvar_RegisterVariable(&r_transparentdepthmasking);
4106 Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4107 Cvar_RegisterVariable(&r_transparent_sortarraysize);
4108 Cvar_RegisterVariable(&r_texture_dds_load);
4109 Cvar_RegisterVariable(&r_texture_dds_save);
4110 Cvar_RegisterVariable(&r_texture_sRGB_2d);
4111 Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4112 Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4113 Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4114 Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4115 Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4116 Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4117 Cvar_RegisterVariable(&r_textureunits);
4118 Cvar_RegisterVariable(&gl_combine);
4119 Cvar_RegisterVariable(&r_viewfbo);
4120 Cvar_RegisterVariable(&r_viewscale);
4121 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4122 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4123 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4124 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4125 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4126 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4127 Cvar_RegisterVariable(&r_glsl);
4128 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4129 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4130 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4131 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4132 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4133 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4134 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4135 Cvar_RegisterVariable(&r_glsl_postprocess);
4136 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4137 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4138 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4139 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4140 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4141 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4142 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4143 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4145 Cvar_RegisterVariable(&r_water);
4146 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4147 Cvar_RegisterVariable(&r_water_clippingplanebias);
4148 Cvar_RegisterVariable(&r_water_refractdistort);
4149 Cvar_RegisterVariable(&r_water_reflectdistort);
4150 Cvar_RegisterVariable(&r_water_scissormode);
4151 Cvar_RegisterVariable(&r_lerpsprites);
4152 Cvar_RegisterVariable(&r_lerpmodels);
4153 Cvar_RegisterVariable(&r_lerplightstyles);
4154 Cvar_RegisterVariable(&r_waterscroll);
4155 Cvar_RegisterVariable(&r_bloom);
4156 Cvar_RegisterVariable(&r_bloom_colorscale);
4157 Cvar_RegisterVariable(&r_bloom_brighten);
4158 Cvar_RegisterVariable(&r_bloom_blur);
4159 Cvar_RegisterVariable(&r_bloom_resolution);
4160 Cvar_RegisterVariable(&r_bloom_colorexponent);
4161 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4162 Cvar_RegisterVariable(&r_hdr);
4163 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4164 Cvar_RegisterVariable(&r_hdr_glowintensity);
4165 Cvar_RegisterVariable(&r_hdr_range);
4166 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4167 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4168 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4169 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4170 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4171 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4172 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4173 Cvar_RegisterVariable(&developer_texturelogging);
4174 Cvar_RegisterVariable(&gl_lightmaps);
4175 Cvar_RegisterVariable(&r_test);
4176 Cvar_RegisterVariable(&r_glsl_saturation);
4177 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4178 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4179 Cvar_RegisterVariable(&r_framedatasize);
4180 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4181 Cvar_SetValue("r_fullbrights", 0);
4182 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4184 Cvar_RegisterVariable(&r_track_sprites);
4185 Cvar_RegisterVariable(&r_track_sprites_flags);
4186 Cvar_RegisterVariable(&r_track_sprites_scalew);
4187 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4188 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4189 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4190 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4191 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4194 extern void R_Textures_Init(void);
4195 extern void GL_Draw_Init(void);
4196 extern void GL_Main_Init(void);
4197 extern void R_Shadow_Init(void);
4198 extern void R_Sky_Init(void);
4199 extern void GL_Surf_Init(void);
4200 extern void R_Particles_Init(void);
4201 extern void R_Explosion_Init(void);
4202 extern void gl_backend_init(void);
4203 extern void Sbar_Init(void);
4204 extern void R_LightningBeams_Init(void);
4205 extern void Mod_RenderInit(void);
4206 extern void Font_Init(void);
4208 void Render_Init(void)
4221 R_LightningBeams_Init();
4230 extern char *ENGINE_EXTENSIONS;
4233 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4234 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4235 gl_version = (const char *)qglGetString(GL_VERSION);
4236 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4240 if (!gl_platformextensions)
4241 gl_platformextensions = "";
4243 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4244 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4245 Con_Printf("GL_VERSION: %s\n", gl_version);
4246 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4247 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4249 VID_CheckExtensions();
4251 // LordHavoc: report supported extensions
4252 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4254 // clear to black (loading plaque will be seen over this)
4255 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4258 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4262 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4264 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4267 p = r_refdef.view.frustum + i;
4272 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4276 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4280 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4284 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4288 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4292 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4296 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4300 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4308 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4312 for (i = 0;i < numplanes;i++)
4319 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4323 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4327 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4331 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4335 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4339 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4343 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4347 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4355 //==================================================================================
4357 // LordHavoc: this stores temporary data used within the same frame
4359 typedef struct r_framedata_mem_s
4361 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4362 size_t size; // how much usable space
4363 size_t current; // how much space in use
4364 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4365 size_t wantedsize; // how much space was allocated
4366 unsigned char *data; // start of real data (16byte aligned)
4370 static r_framedata_mem_t *r_framedata_mem;
4372 void R_FrameData_Reset(void)
4374 while (r_framedata_mem)
4376 r_framedata_mem_t *next = r_framedata_mem->purge;
4377 Mem_Free(r_framedata_mem);
4378 r_framedata_mem = next;
4382 void R_FrameData_Resize(void)
4385 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4386 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4387 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4389 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4390 newmem->wantedsize = wantedsize;
4391 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4392 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4393 newmem->current = 0;
4395 newmem->purge = r_framedata_mem;
4396 r_framedata_mem = newmem;
4400 void R_FrameData_NewFrame(void)
4402 R_FrameData_Resize();
4403 if (!r_framedata_mem)
4405 // if we ran out of space on the last frame, free the old memory now
4406 while (r_framedata_mem->purge)
4408 // repeatedly remove the second item in the list, leaving only head
4409 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4410 Mem_Free(r_framedata_mem->purge);
4411 r_framedata_mem->purge = next;
4413 // reset the current mem pointer
4414 r_framedata_mem->current = 0;
4415 r_framedata_mem->mark = 0;
4418 void *R_FrameData_Alloc(size_t size)
4422 // align to 16 byte boundary - the data pointer is already aligned, so we
4423 // only need to ensure the size of every allocation is also aligned
4424 size = (size + 15) & ~15;
4426 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4428 // emergency - we ran out of space, allocate more memory
4429 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4430 R_FrameData_Resize();
4433 data = r_framedata_mem->data + r_framedata_mem->current;
4434 r_framedata_mem->current += size;
4436 // count the usage for stats
4437 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4438 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4440 return (void *)data;
4443 void *R_FrameData_Store(size_t size, void *data)
4445 void *d = R_FrameData_Alloc(size);
4447 memcpy(d, data, size);
4451 void R_FrameData_SetMark(void)
4453 if (!r_framedata_mem)
4455 r_framedata_mem->mark = r_framedata_mem->current;
4458 void R_FrameData_ReturnToMark(void)
4460 if (!r_framedata_mem)
4462 r_framedata_mem->current = r_framedata_mem->mark;
4465 //==================================================================================
4467 // LordHavoc: animcache originally written by Echon, rewritten since then
4470 * Animation cache prevents re-generating mesh data for an animated model
4471 * multiple times in one frame for lighting, shadowing, reflections, etc.
4474 void R_AnimCache_Free(void)
4478 void R_AnimCache_ClearCache(void)
4481 entity_render_t *ent;
4483 for (i = 0;i < r_refdef.scene.numentities;i++)
4485 ent = r_refdef.scene.entities[i];
4486 ent->animcache_vertex3f = NULL;
4487 ent->animcache_normal3f = NULL;
4488 ent->animcache_svector3f = NULL;
4489 ent->animcache_tvector3f = NULL;
4490 ent->animcache_vertexmesh = NULL;
4491 ent->animcache_vertex3fbuffer = NULL;
4492 ent->animcache_vertexmeshbuffer = NULL;
4496 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4500 // check if we need the meshbuffers
4501 if (!vid.useinterleavedarrays)
4504 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4505 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4506 // TODO: upload vertex3f buffer?
4507 if (ent->animcache_vertexmesh)
4509 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4510 for (i = 0;i < numvertices;i++)
4511 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4512 if (ent->animcache_svector3f)
4513 for (i = 0;i < numvertices;i++)
4514 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4515 if (ent->animcache_tvector3f)
4516 for (i = 0;i < numvertices;i++)
4517 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4518 if (ent->animcache_normal3f)
4519 for (i = 0;i < numvertices;i++)
4520 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4521 // TODO: upload vertexmeshbuffer?
4525 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4527 dp_model_t *model = ent->model;
4529 // see if it's already cached this frame
4530 if (ent->animcache_vertex3f)
4532 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4533 if (wantnormals || wanttangents)
4535 if (ent->animcache_normal3f)
4536 wantnormals = false;
4537 if (ent->animcache_svector3f)
4538 wanttangents = false;
4539 if (wantnormals || wanttangents)
4541 numvertices = model->surfmesh.num_vertices;
4543 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4546 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4549 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4550 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4556 // see if this ent is worth caching
4557 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4559 // get some memory for this entity and generate mesh data
4560 numvertices = model->surfmesh.num_vertices;
4561 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4563 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4566 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4567 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4569 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4570 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4575 void R_AnimCache_CacheVisibleEntities(void)
4578 qboolean wantnormals = true;
4579 qboolean wanttangents = !r_showsurfaces.integer;
4581 switch(vid.renderpath)
4583 case RENDERPATH_GL20:
4584 case RENDERPATH_D3D9:
4585 case RENDERPATH_D3D10:
4586 case RENDERPATH_D3D11:
4587 case RENDERPATH_GLES2:
4589 case RENDERPATH_GL11:
4590 case RENDERPATH_GL13:
4591 case RENDERPATH_GLES1:
4592 wanttangents = false;
4594 case RENDERPATH_SOFT:
4598 if (r_shownormals.integer)
4599 wanttangents = wantnormals = true;
4601 // TODO: thread this
4602 // NOTE: R_PrepareRTLights() also caches entities
4604 for (i = 0;i < r_refdef.scene.numentities;i++)
4605 if (r_refdef.viewcache.entityvisible[i])
4606 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4609 //==================================================================================
4611 static void R_View_UpdateEntityLighting (void)
4614 entity_render_t *ent;
4615 vec3_t tempdiffusenormal, avg;
4616 vec_t f, fa, fd, fdd;
4617 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4619 for (i = 0;i < r_refdef.scene.numentities;i++)
4621 ent = r_refdef.scene.entities[i];
4623 // skip unseen models
4624 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4628 if (ent->model && ent->model->brush.num_leafs)
4630 // TODO: use modellight for r_ambient settings on world?
4631 VectorSet(ent->modellight_ambient, 0, 0, 0);
4632 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4633 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4637 // fetch the lighting from the worldmodel data
4638 VectorClear(ent->modellight_ambient);
4639 VectorClear(ent->modellight_diffuse);
4640 VectorClear(tempdiffusenormal);
4641 if (ent->flags & RENDER_LIGHT)
4644 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4646 // complete lightning for lit sprites
4647 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4648 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4650 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4651 org[2] = org[2] + r_overheadsprites_pushback.value;
4652 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4655 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4657 if(ent->flags & RENDER_EQUALIZE)
4659 // first fix up ambient lighting...
4660 if(r_equalize_entities_minambient.value > 0)
4662 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4665 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4666 if(fa < r_equalize_entities_minambient.value * fd)
4669 // fa'/fd' = minambient
4670 // fa'+0.25*fd' = fa+0.25*fd
4672 // fa' = fd' * minambient
4673 // fd'*(0.25+minambient) = fa+0.25*fd
4675 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4676 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4678 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4679 f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4680 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4681 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4686 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4688 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4689 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4693 // adjust brightness and saturation to target
4694 avg[0] = avg[1] = avg[2] = fa / f;
4695 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4696 avg[0] = avg[1] = avg[2] = fd / f;
4697 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4703 VectorSet(ent->modellight_ambient, 1, 1, 1);
4705 // move the light direction into modelspace coordinates for lighting code
4706 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4707 if(VectorLength2(ent->modellight_lightdir) == 0)
4708 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4709 VectorNormalize(ent->modellight_lightdir);
4713 #define MAX_LINEOFSIGHTTRACES 64
4715 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4718 vec3_t boxmins, boxmaxs;
4721 dp_model_t *model = r_refdef.scene.worldmodel;
4723 if (!model || !model->brush.TraceLineOfSight)
4726 // expand the box a little
4727 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4728 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4729 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4730 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4731 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4732 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4734 // return true if eye is inside enlarged box
4735 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4739 VectorCopy(eye, start);
4740 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4741 if (model->brush.TraceLineOfSight(model, start, end))
4744 // try various random positions
4745 for (i = 0;i < numsamples;i++)
4747 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4748 if (model->brush.TraceLineOfSight(model, start, end))
4756 static void R_View_UpdateEntityVisible (void)
4761 entity_render_t *ent;
4763 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4764 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4765 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4766 : RENDER_EXTERIORMODEL;
4767 if (!r_drawviewmodel.integer)
4768 renderimask |= RENDER_VIEWMODEL;
4769 if (!r_drawexteriormodel.integer)
4770 renderimask |= RENDER_EXTERIORMODEL;
4771 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4773 // worldmodel can check visibility
4774 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4775 for (i = 0;i < r_refdef.scene.numentities;i++)
4777 ent = r_refdef.scene.entities[i];
4778 if (!(ent->flags & renderimask))
4779 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)))
4780 if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4781 r_refdef.viewcache.entityvisible[i] = true;
4786 // no worldmodel or it can't check visibility
4787 for (i = 0;i < r_refdef.scene.numentities;i++)
4789 ent = r_refdef.scene.entities[i];
4790 r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4793 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4794 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4796 for (i = 0;i < r_refdef.scene.numentities;i++)
4798 if (!r_refdef.viewcache.entityvisible[i])
4800 ent = r_refdef.scene.entities[i];
4801 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4803 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4805 continue; // temp entities do pvs only
4806 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4807 ent->last_trace_visibility = realtime;
4808 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4809 r_refdef.viewcache.entityvisible[i] = 0;
4815 /// only used if skyrendermasked, and normally returns false
4816 int R_DrawBrushModelsSky (void)
4819 entity_render_t *ent;
4822 for (i = 0;i < r_refdef.scene.numentities;i++)
4824 if (!r_refdef.viewcache.entityvisible[i])
4826 ent = r_refdef.scene.entities[i];
4827 if (!ent->model || !ent->model->DrawSky)
4829 ent->model->DrawSky(ent);
4835 static void R_DrawNoModel(entity_render_t *ent);
4836 static void R_DrawModels(void)
4839 entity_render_t *ent;
4841 for (i = 0;i < r_refdef.scene.numentities;i++)
4843 if (!r_refdef.viewcache.entityvisible[i])
4845 ent = r_refdef.scene.entities[i];
4846 r_refdef.stats.entities++;
4847 if (ent->model && ent->model->Draw != NULL)
4848 ent->model->Draw(ent);
4854 static void R_DrawModelsDepth(void)
4857 entity_render_t *ent;
4859 for (i = 0;i < r_refdef.scene.numentities;i++)
4861 if (!r_refdef.viewcache.entityvisible[i])
4863 ent = r_refdef.scene.entities[i];
4864 if (ent->model && ent->model->DrawDepth != NULL)
4865 ent->model->DrawDepth(ent);
4869 static void R_DrawModelsDebug(void)
4872 entity_render_t *ent;
4874 for (i = 0;i < r_refdef.scene.numentities;i++)
4876 if (!r_refdef.viewcache.entityvisible[i])
4878 ent = r_refdef.scene.entities[i];
4879 if (ent->model && ent->model->DrawDebug != NULL)
4880 ent->model->DrawDebug(ent);
4884 static void R_DrawModelsAddWaterPlanes(void)
4887 entity_render_t *ent;
4889 for (i = 0;i < r_refdef.scene.numentities;i++)
4891 if (!r_refdef.viewcache.entityvisible[i])
4893 ent = r_refdef.scene.entities[i];
4894 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4895 ent->model->DrawAddWaterPlanes(ent);
4899 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4901 if (r_hdr_irisadaptation.integer)
4905 vec3_t diffusenormal;
4910 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4911 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4912 brightness = max(0.0000001f, brightness);
4913 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4914 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4915 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4916 current = r_hdr_irisadaptation_value.value;
4918 current = min(current + adjust, goal);
4919 else if (current > goal)
4920 current = max(current - adjust, goal);
4921 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4922 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4924 else if (r_hdr_irisadaptation_value.value != 1.0f)
4925 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4928 static void R_View_SetFrustum(const int *scissor)
4931 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4932 vec3_t forward, left, up, origin, v;
4936 // flipped x coordinates (because x points left here)
4937 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4938 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4940 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4941 switch(vid.renderpath)
4943 case RENDERPATH_D3D9:
4944 case RENDERPATH_D3D10:
4945 case RENDERPATH_D3D11:
4946 // non-flipped y coordinates
4947 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4948 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4950 case RENDERPATH_SOFT:
4951 case RENDERPATH_GL11:
4952 case RENDERPATH_GL13:
4953 case RENDERPATH_GL20:
4954 case RENDERPATH_GLES1:
4955 case RENDERPATH_GLES2:
4956 // non-flipped y coordinates
4957 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4958 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4963 // we can't trust r_refdef.view.forward and friends in reflected scenes
4964 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4967 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4968 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4969 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4970 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4971 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4972 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4973 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4974 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4975 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4976 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4977 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4978 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4982 zNear = r_refdef.nearclip;
4983 nudge = 1.0 - 1.0 / (1<<23);
4984 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4985 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4986 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4987 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4988 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4989 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4990 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4991 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4997 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4998 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4999 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5000 r_refdef.view.frustum[0].dist = m[15] - m[12];
5002 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5003 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5004 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5005 r_refdef.view.frustum[1].dist = m[15] + m[12];
5007 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5008 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5009 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5010 r_refdef.view.frustum[2].dist = m[15] - m[13];
5012 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5013 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5014 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5015 r_refdef.view.frustum[3].dist = m[15] + m[13];
5017 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5018 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5019 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5020 r_refdef.view.frustum[4].dist = m[15] - m[14];
5022 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5023 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5024 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5025 r_refdef.view.frustum[5].dist = m[15] + m[14];
5028 if (r_refdef.view.useperspective)
5030 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5031 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]);
5032 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]);
5033 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]);
5034 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]);
5036 // then the normals from the corners relative to origin
5037 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5038 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5039 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5040 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5042 // in a NORMAL view, forward cross left == up
5043 // in a REFLECTED view, forward cross left == down
5044 // so our cross products above need to be adjusted for a left handed coordinate system
5045 CrossProduct(forward, left, v);
5046 if(DotProduct(v, up) < 0)
5048 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5049 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5050 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5051 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5054 // Leaving those out was a mistake, those were in the old code, and they
5055 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5056 // I couldn't reproduce it after adding those normalizations. --blub
5057 VectorNormalize(r_refdef.view.frustum[0].normal);
5058 VectorNormalize(r_refdef.view.frustum[1].normal);
5059 VectorNormalize(r_refdef.view.frustum[2].normal);
5060 VectorNormalize(r_refdef.view.frustum[3].normal);
5062 // make the corners absolute
5063 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5064 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5065 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5066 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5069 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5071 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5072 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5073 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5074 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5075 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5079 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5080 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5081 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5082 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5083 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5084 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5085 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5086 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5087 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5088 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5090 r_refdef.view.numfrustumplanes = 5;
5092 if (r_refdef.view.useclipplane)
5094 r_refdef.view.numfrustumplanes = 6;
5095 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5098 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5099 PlaneClassify(r_refdef.view.frustum + i);
5101 // LordHavoc: note to all quake engine coders, Quake had a special case
5102 // for 90 degrees which assumed a square view (wrong), so I removed it,
5103 // Quake2 has it disabled as well.
5105 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5106 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5107 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5108 //PlaneClassify(&frustum[0]);
5110 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5111 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5112 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5113 //PlaneClassify(&frustum[1]);
5115 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5116 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5117 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5118 //PlaneClassify(&frustum[2]);
5120 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5121 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5122 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5123 //PlaneClassify(&frustum[3]);
5126 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5127 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5128 //PlaneClassify(&frustum[4]);
5131 void R_View_UpdateWithScissor(const int *myscissor)
5133 R_Main_ResizeViewCache();
5134 R_View_SetFrustum(myscissor);
5135 R_View_WorldVisibility(r_refdef.view.useclipplane);
5136 R_View_UpdateEntityVisible();
5137 R_View_UpdateEntityLighting();
5140 void R_View_Update(void)
5142 R_Main_ResizeViewCache();
5143 R_View_SetFrustum(NULL);
5144 R_View_WorldVisibility(r_refdef.view.useclipplane);
5145 R_View_UpdateEntityVisible();
5146 R_View_UpdateEntityLighting();
5149 float viewscalefpsadjusted = 1.0f;
5151 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5153 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5154 scale = bound(0.03125f, scale, 1.0f);
5155 *outwidth = (int)ceil(width * scale);
5156 *outheight = (int)ceil(height * scale);
5159 void R_Mesh_SetMainRenderTargets(void)
5161 if (r_bloomstate.fbo_framebuffer)
5162 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5164 R_Mesh_ResetRenderTargets();
5167 void R_SetupView(qboolean allowwaterclippingplane)
5169 const float *customclipplane = NULL;
5171 int scaledwidth, scaledheight;
5172 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5174 // LordHavoc: couldn't figure out how to make this approach the
5175 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5176 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5177 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5178 dist = r_refdef.view.clipplane.dist;
5179 plane[0] = r_refdef.view.clipplane.normal[0];
5180 plane[1] = r_refdef.view.clipplane.normal[1];
5181 plane[2] = r_refdef.view.clipplane.normal[2];
5183 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5186 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5187 if (!r_refdef.view.useperspective)
5188 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5189 else if (vid.stencil && r_useinfinitefarclip.integer)
5190 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5192 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5193 R_Mesh_SetMainRenderTargets();
5194 R_SetViewport(&r_refdef.view.viewport);
5195 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5197 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5198 float screenplane[4];
5199 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5200 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5201 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5202 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5203 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5207 void R_EntityMatrix(const matrix4x4_t *matrix)
5209 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5211 gl_modelmatrixchanged = false;
5212 gl_modelmatrix = *matrix;
5213 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5214 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5215 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5216 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5218 switch(vid.renderpath)
5220 case RENDERPATH_D3D9:
5222 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5223 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5226 case RENDERPATH_D3D10:
5227 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5229 case RENDERPATH_D3D11:
5230 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5232 case RENDERPATH_GL11:
5233 case RENDERPATH_GL13:
5234 case RENDERPATH_GLES1:
5235 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5237 case RENDERPATH_SOFT:
5238 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5239 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5241 case RENDERPATH_GL20:
5242 case RENDERPATH_GLES2:
5243 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5244 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5250 void R_ResetViewRendering2D(void)
5252 r_viewport_t viewport;
5255 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5256 R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5257 R_Mesh_ResetRenderTargets();
5258 R_SetViewport(&viewport);
5259 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5260 GL_Color(1, 1, 1, 1);
5261 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5262 GL_BlendFunc(GL_ONE, GL_ZERO);
5263 GL_ScissorTest(false);
5264 GL_DepthMask(false);
5265 GL_DepthRange(0, 1);
5266 GL_DepthTest(false);
5267 GL_DepthFunc(GL_LEQUAL);
5268 R_EntityMatrix(&identitymatrix);
5269 R_Mesh_ResetTextureState();
5270 GL_PolygonOffset(0, 0);
5271 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5272 switch(vid.renderpath)
5274 case RENDERPATH_GL11:
5275 case RENDERPATH_GL13:
5276 case RENDERPATH_GL20:
5277 case RENDERPATH_GLES1:
5278 case RENDERPATH_GLES2:
5279 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5281 case RENDERPATH_D3D9:
5282 case RENDERPATH_D3D10:
5283 case RENDERPATH_D3D11:
5284 case RENDERPATH_SOFT:
5287 GL_CullFace(GL_NONE);
5290 void R_ResetViewRendering3D(void)
5295 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5296 GL_Color(1, 1, 1, 1);
5297 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5298 GL_BlendFunc(GL_ONE, GL_ZERO);
5299 GL_ScissorTest(true);
5301 GL_DepthRange(0, 1);
5303 GL_DepthFunc(GL_LEQUAL);
5304 R_EntityMatrix(&identitymatrix);
5305 R_Mesh_ResetTextureState();
5306 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5307 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5308 switch(vid.renderpath)
5310 case RENDERPATH_GL11:
5311 case RENDERPATH_GL13:
5312 case RENDERPATH_GL20:
5313 case RENDERPATH_GLES1:
5314 case RENDERPATH_GLES2:
5315 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5317 case RENDERPATH_D3D9:
5318 case RENDERPATH_D3D10:
5319 case RENDERPATH_D3D11:
5320 case RENDERPATH_SOFT:
5323 GL_CullFace(r_refdef.view.cullface_back);
5328 R_RenderView_UpdateViewVectors
5331 static void R_RenderView_UpdateViewVectors(void)
5333 // break apart the view matrix into vectors for various purposes
5334 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5335 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5336 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5337 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5338 // make an inverted copy of the view matrix for tracking sprites
5339 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5342 void R_RenderScene(void);
5343 void R_RenderWaterPlanes(void);
5345 static void R_Water_StartFrame(void)
5348 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5349 r_waterstate_waterplane_t *p;
5351 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5354 switch(vid.renderpath)
5356 case RENDERPATH_GL20:
5357 case RENDERPATH_D3D9:
5358 case RENDERPATH_D3D10:
5359 case RENDERPATH_D3D11:
5360 case RENDERPATH_SOFT:
5361 case RENDERPATH_GLES2:
5363 case RENDERPATH_GL11:
5364 case RENDERPATH_GL13:
5365 case RENDERPATH_GLES1:
5369 // set waterwidth and waterheight to the water resolution that will be
5370 // used (often less than the screen resolution for faster rendering)
5371 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5372 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5374 // calculate desired texture sizes
5375 // can't use water if the card does not support the texture size
5376 if (!r_water.integer || r_showsurfaces.integer)
5377 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5378 else if (vid.support.arb_texture_non_power_of_two)
5380 texturewidth = waterwidth;
5381 textureheight = waterheight;
5382 camerawidth = waterwidth;
5383 cameraheight = waterheight;
5387 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5388 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5389 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5390 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5393 // allocate textures as needed
5394 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5396 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5397 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5399 if (p->texture_refraction)
5400 R_FreeTexture(p->texture_refraction);
5401 p->texture_refraction = NULL;
5402 if (p->texture_reflection)
5403 R_FreeTexture(p->texture_reflection);
5404 p->texture_reflection = NULL;
5405 if (p->texture_camera)
5406 R_FreeTexture(p->texture_camera);
5407 p->texture_camera = NULL;
5409 memset(&r_waterstate, 0, sizeof(r_waterstate));
5410 r_waterstate.texturewidth = texturewidth;
5411 r_waterstate.textureheight = textureheight;
5412 r_waterstate.camerawidth = camerawidth;
5413 r_waterstate.cameraheight = cameraheight;
5416 if (r_waterstate.texturewidth)
5418 r_waterstate.enabled = true;
5420 // when doing a reduced render (HDR) we want to use a smaller area
5421 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5422 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5424 // set up variables that will be used in shader setup
5425 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5426 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5427 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5428 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5431 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5432 r_waterstate.numwaterplanes = 0;
5435 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5437 int triangleindex, planeindex;
5443 r_waterstate_waterplane_t *p;
5444 texture_t *t = R_GetCurrentTexture(surface->texture);
5446 // just use the first triangle with a valid normal for any decisions
5447 VectorClear(normal);
5448 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5450 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5451 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5452 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5453 TriangleNormal(vert[0], vert[1], vert[2], normal);
5454 if (VectorLength2(normal) >= 0.001)
5458 VectorCopy(normal, plane.normal);
5459 VectorNormalize(plane.normal);
5460 plane.dist = DotProduct(vert[0], plane.normal);
5461 PlaneClassify(&plane);
5462 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5464 // skip backfaces (except if nocullface is set)
5465 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5467 VectorNegate(plane.normal, plane.normal);
5469 PlaneClassify(&plane);
5473 // find a matching plane if there is one
5474 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5475 if(p->camera_entity == t->camera_entity)
5476 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5478 if (planeindex >= r_waterstate.maxwaterplanes)
5479 return; // nothing we can do, out of planes
5481 // if this triangle does not fit any known plane rendered this frame, add one
5482 if (planeindex >= r_waterstate.numwaterplanes)
5484 // store the new plane
5485 r_waterstate.numwaterplanes++;
5487 // clear materialflags and pvs
5488 p->materialflags = 0;
5489 p->pvsvalid = false;
5490 p->camera_entity = t->camera_entity;
5491 VectorCopy(surface->mins, p->mins);
5492 VectorCopy(surface->maxs, p->maxs);
5497 p->mins[0] = min(p->mins[0], surface->mins[0]);
5498 p->mins[1] = min(p->mins[1], surface->mins[1]);
5499 p->mins[2] = min(p->mins[2], surface->mins[2]);
5500 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5501 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5502 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5504 // merge this surface's materialflags into the waterplane
5505 p->materialflags |= t->currentmaterialflags;
5506 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5508 // merge this surface's PVS into the waterplane
5509 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5510 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5511 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5513 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5519 static void R_Water_ProcessPlanes(void)
5522 r_refdef_view_t originalview;
5523 r_refdef_view_t myview;
5525 r_waterstate_waterplane_t *p;
5528 originalview = r_refdef.view;
5530 // make sure enough textures are allocated
5531 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5533 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5535 if (!p->texture_refraction)
5536 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5537 if (!p->texture_refraction)
5540 else if (p->materialflags & MATERIALFLAG_CAMERA)
5542 if (!p->texture_camera)
5543 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5544 if (!p->texture_camera)
5548 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5550 if (!p->texture_reflection)
5551 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5552 if (!p->texture_reflection)
5558 r_refdef.view = originalview;
5559 r_refdef.view.showdebug = false;
5560 r_refdef.view.width = r_waterstate.waterwidth;
5561 r_refdef.view.height = r_waterstate.waterheight;
5562 r_refdef.view.useclipplane = true;
5563 myview = r_refdef.view;
5564 r_waterstate.renderingscene = true;
5565 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5567 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5569 r_refdef.view = myview;
5570 if(r_water_scissormode.integer)
5573 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5574 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5577 // render reflected scene and copy into texture
5578 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5579 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5580 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5581 r_refdef.view.clipplane = p->plane;
5583 // reverse the cullface settings for this render
5584 r_refdef.view.cullface_front = GL_FRONT;
5585 r_refdef.view.cullface_back = GL_BACK;
5586 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5588 r_refdef.view.usecustompvs = true;
5590 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5592 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5595 R_ResetViewRendering3D();
5596 R_ClearScreen(r_refdef.fogenabled);
5597 if(r_water_scissormode.integer & 2)
5598 R_View_UpdateWithScissor(myscissor);
5601 if(r_water_scissormode.integer & 1)
5602 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5605 R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5608 // render the normal view scene and copy into texture
5609 // (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)
5610 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5612 r_refdef.view = myview;
5613 if(r_water_scissormode.integer)
5616 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5617 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5620 r_waterstate.renderingrefraction = true;
5622 r_refdef.view.clipplane = p->plane;
5623 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5624 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5626 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5628 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5629 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5630 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5631 R_RenderView_UpdateViewVectors();
5632 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5634 r_refdef.view.usecustompvs = true;
5635 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);
5639 PlaneClassify(&r_refdef.view.clipplane);
5641 R_ResetViewRendering3D();
5642 R_ClearScreen(r_refdef.fogenabled);
5643 if(r_water_scissormode.integer & 2)
5644 R_View_UpdateWithScissor(myscissor);
5647 if(r_water_scissormode.integer & 1)
5648 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5651 R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5652 r_waterstate.renderingrefraction = false;
5654 else if (p->materialflags & MATERIALFLAG_CAMERA)
5656 r_refdef.view = myview;
5658 r_refdef.view.clipplane = p->plane;
5659 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5660 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5662 r_refdef.view.width = r_waterstate.camerawidth;
5663 r_refdef.view.height = r_waterstate.cameraheight;
5664 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5665 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5667 if(p->camera_entity)
5669 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5670 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5673 // note: all of the view is used for displaying... so
5674 // there is no use in scissoring
5676 // reverse the cullface settings for this render
5677 r_refdef.view.cullface_front = GL_FRONT;
5678 r_refdef.view.cullface_back = GL_BACK;
5679 // also reverse the view matrix
5680 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
5681 R_RenderView_UpdateViewVectors();
5682 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5684 r_refdef.view.usecustompvs = true;
5685 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);
5688 // camera needs no clipplane
5689 r_refdef.view.useclipplane = false;
5691 PlaneClassify(&r_refdef.view.clipplane);
5693 R_ResetViewRendering3D();
5694 R_ClearScreen(r_refdef.fogenabled);
5698 R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5699 r_waterstate.renderingrefraction = false;
5703 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5704 r_waterstate.renderingscene = false;
5705 r_refdef.view = originalview;
5706 R_ResetViewRendering3D();
5707 R_ClearScreen(r_refdef.fogenabled);
5711 r_refdef.view = originalview;
5712 r_waterstate.renderingscene = false;
5713 Cvar_SetValueQuick(&r_water, 0);
5714 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5718 void R_Bloom_StartFrame(void)
5720 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5721 int viewwidth, viewheight;
5724 if (r_viewscale_fpsscaling.integer)
5726 double actualframetime;
5727 double targetframetime;
5729 actualframetime = r_refdef.lastdrawscreentime;
5730 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5731 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5732 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5733 if (r_viewscale_fpsscaling_stepsize.value > 0)
5734 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5735 viewscalefpsadjusted += adjust;
5736 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5739 viewscalefpsadjusted = 1.0f;
5741 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5743 switch(vid.renderpath)
5745 case RENDERPATH_GL20:
5746 case RENDERPATH_D3D9:
5747 case RENDERPATH_D3D10:
5748 case RENDERPATH_D3D11:
5749 case RENDERPATH_SOFT:
5750 case RENDERPATH_GLES2:
5752 case RENDERPATH_GL11:
5753 case RENDERPATH_GL13:
5754 case RENDERPATH_GLES1:
5758 // set bloomwidth and bloomheight to the bloom resolution that will be
5759 // used (often less than the screen resolution for faster rendering)
5760 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5761 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5762 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5763 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5764 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5766 // calculate desired texture sizes
5767 if (vid.support.arb_texture_non_power_of_two)
5769 screentexturewidth = vid.width;
5770 screentextureheight = vid.height;
5771 bloomtexturewidth = r_bloomstate.bloomwidth;
5772 bloomtextureheight = r_bloomstate.bloomheight;
5776 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5777 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5778 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5779 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5782 if ((r_hdr.integer || 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))
5784 Cvar_SetValueQuick(&r_hdr, 0);
5785 Cvar_SetValueQuick(&r_bloom, 0);
5786 Cvar_SetValueQuick(&r_motionblur, 0);
5787 Cvar_SetValueQuick(&r_damageblur, 0);
5790 if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5791 screentexturewidth = screentextureheight = 0;
5792 if (!r_hdr.integer && !r_bloom.integer)
5793 bloomtexturewidth = bloomtextureheight = 0;
5795 textype = TEXTYPE_COLORBUFFER;
5796 switch (vid.renderpath)
5798 case RENDERPATH_GL20:
5799 case RENDERPATH_GLES2:
5800 if (vid.support.ext_framebuffer_object)
5802 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5803 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5806 case RENDERPATH_GL11:
5807 case RENDERPATH_GL13:
5808 case RENDERPATH_GLES1:
5809 case RENDERPATH_D3D9:
5810 case RENDERPATH_D3D10:
5811 case RENDERPATH_D3D11:
5812 case RENDERPATH_SOFT:
5816 // allocate textures as needed
5817 if (r_bloomstate.screentexturewidth != screentexturewidth
5818 || r_bloomstate.screentextureheight != screentextureheight
5819 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5820 || r_bloomstate.bloomtextureheight != bloomtextureheight
5821 || r_bloomstate.texturetype != textype
5822 || r_bloomstate.viewfbo != r_viewfbo.integer)
5824 if (r_bloomstate.texture_bloom)
5825 R_FreeTexture(r_bloomstate.texture_bloom);
5826 r_bloomstate.texture_bloom = NULL;
5827 if (r_bloomstate.texture_screen)
5828 R_FreeTexture(r_bloomstate.texture_screen);
5829 r_bloomstate.texture_screen = NULL;
5830 if (r_bloomstate.fbo_framebuffer)
5831 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5832 r_bloomstate.fbo_framebuffer = 0;
5833 if (r_bloomstate.texture_framebuffercolor)
5834 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5835 r_bloomstate.texture_framebuffercolor = NULL;
5836 if (r_bloomstate.texture_framebufferdepth)
5837 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5838 r_bloomstate.texture_framebufferdepth = NULL;
5839 r_bloomstate.screentexturewidth = screentexturewidth;
5840 r_bloomstate.screentextureheight = screentextureheight;
5841 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5842 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5843 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5845 // FIXME: choose depth bits based on a cvar
5846 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5847 r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5848 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5849 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5850 // render depth into one texture and normalmap into the other
5854 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5855 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5856 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5857 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5858 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5861 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5862 r_bloomstate.bloomtextureheight = bloomtextureheight;
5863 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5864 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5865 r_bloomstate.viewfbo = r_viewfbo.integer;
5866 r_bloomstate.texturetype = textype;
5869 // when doing a reduced render (HDR) we want to use a smaller area
5870 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5871 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5872 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5873 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5874 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5876 // set up a texcoord array for the full resolution screen image
5877 // (we have to keep this around to copy back during final render)
5878 r_bloomstate.screentexcoord2f[0] = 0;
5879 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5880 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5881 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5882 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5883 r_bloomstate.screentexcoord2f[5] = 0;
5884 r_bloomstate.screentexcoord2f[6] = 0;
5885 r_bloomstate.screentexcoord2f[7] = 0;
5887 // set up a texcoord array for the reduced resolution bloom image
5888 // (which will be additive blended over the screen image)
5889 r_bloomstate.bloomtexcoord2f[0] = 0;
5890 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5891 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5892 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5893 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5894 r_bloomstate.bloomtexcoord2f[5] = 0;
5895 r_bloomstate.bloomtexcoord2f[6] = 0;
5896 r_bloomstate.bloomtexcoord2f[7] = 0;
5898 switch(vid.renderpath)
5900 case RENDERPATH_GL11:
5901 case RENDERPATH_GL13:
5902 case RENDERPATH_GL20:
5903 case RENDERPATH_SOFT:
5904 case RENDERPATH_GLES1:
5905 case RENDERPATH_GLES2:
5907 case RENDERPATH_D3D9:
5908 case RENDERPATH_D3D10:
5909 case RENDERPATH_D3D11:
5912 for (i = 0;i < 4;i++)
5914 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5915 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5916 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5917 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5923 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5925 r_bloomstate.enabled = true;
5926 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5929 R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
5931 if (r_bloomstate.fbo_framebuffer)
5932 r_refdef.view.clear = true;
5935 void R_Bloom_CopyBloomTexture(float colorscale)
5937 r_refdef.stats.bloom++;
5939 // scale down screen texture to the bloom texture size
5941 R_Mesh_SetMainRenderTargets();
5942 R_SetViewport(&r_bloomstate.viewport);
5943 GL_BlendFunc(GL_ONE, GL_ZERO);
5944 GL_Color(colorscale, colorscale, colorscale, 1);
5945 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
5946 switch(vid.renderpath)
5948 case RENDERPATH_GL11:
5949 case RENDERPATH_GL13:
5950 case RENDERPATH_GL20:
5951 case RENDERPATH_GLES1:
5952 case RENDERPATH_GLES2:
5953 case RENDERPATH_SOFT:
5954 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5956 case RENDERPATH_D3D9:
5957 case RENDERPATH_D3D10:
5958 case RENDERPATH_D3D11:
5959 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5962 // TODO: do boxfilter scale-down in shader?
5963 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5964 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5965 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5967 // we now have a bloom image in the framebuffer
5968 // copy it into the bloom image texture for later processing
5969 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
5970 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5973 void R_Bloom_CopyHDRTexture(void)
5975 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5976 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5979 void R_Bloom_MakeTexture(void)
5982 float xoffset, yoffset, r, brighten;
5984 r_refdef.stats.bloom++;
5986 R_ResetViewRendering2D();
5988 // we have a bloom image in the framebuffer
5990 R_SetViewport(&r_bloomstate.viewport);
5992 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5995 r = bound(0, r_bloom_colorexponent.value / x, 1);
5996 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5998 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5999 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6000 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6001 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6003 // copy the vertically blurred bloom view to a texture
6004 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6005 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6008 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6009 brighten = r_bloom_brighten.value;
6010 if (r_bloomstate.hdr)
6011 brighten *= r_hdr_range.value;
6012 brighten = sqrt(brighten);
6014 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6015 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
6017 for (dir = 0;dir < 2;dir++)
6019 // blend on at multiple vertical offsets to achieve a vertical blur
6020 // TODO: do offset blends using GLSL
6021 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6022 GL_BlendFunc(GL_ONE, GL_ZERO);
6023 for (x = -range;x <= range;x++)
6025 if (!dir){xoffset = 0;yoffset = x;}
6026 else {xoffset = x;yoffset = 0;}
6027 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6028 yoffset /= (float)r_bloomstate.bloomtextureheight;
6029 // compute a texcoord array with the specified x and y offset
6030 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6031 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6032 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6033 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6034 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6035 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6036 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6037 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6038 // this r value looks like a 'dot' particle, fading sharply to
6039 // black at the edges
6040 // (probably not realistic but looks good enough)
6041 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6042 //r = brighten/(range*2+1);
6043 r = brighten / (range * 2 + 1);
6045 r *= (1 - x*x/(float)(range*range));
6046 GL_Color(r, r, r, 1);
6047 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6048 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6049 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6050 GL_BlendFunc(GL_ONE, GL_ONE);
6053 // copy the vertically blurred bloom view to a texture
6054 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6055 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6059 void R_HDR_RenderBloomTexture(void)
6061 int oldwidth, oldheight;
6062 float oldcolorscale;
6063 qboolean oldwaterstate;
6065 oldwaterstate = r_waterstate.enabled;
6066 oldcolorscale = r_refdef.view.colorscale;
6067 oldwidth = r_refdef.view.width;
6068 oldheight = r_refdef.view.height;
6069 r_refdef.view.width = r_bloomstate.bloomwidth;
6070 r_refdef.view.height = r_bloomstate.bloomheight;
6072 if(r_hdr.integer < 2)
6073 r_waterstate.enabled = false;
6075 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6076 // TODO: add exposure compensation features
6077 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6079 r_refdef.view.showdebug = false;
6080 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6082 R_ResetViewRendering3D();
6084 R_ClearScreen(r_refdef.fogenabled);
6085 if (r_timereport_active)
6086 R_TimeReport("HDRclear");
6089 if (r_timereport_active)
6090 R_TimeReport("visibility");
6092 // only do secondary renders with HDR if r_hdr is 2 or higher
6093 r_waterstate.numwaterplanes = 0;
6094 if (r_waterstate.enabled)
6095 R_RenderWaterPlanes();
6097 r_refdef.view.showdebug = true;
6099 r_waterstate.numwaterplanes = 0;
6101 R_ResetViewRendering2D();
6103 R_Bloom_CopyHDRTexture();
6104 R_Bloom_MakeTexture();
6106 // restore the view settings
6107 r_waterstate.enabled = oldwaterstate;
6108 r_refdef.view.width = oldwidth;
6109 r_refdef.view.height = oldheight;
6110 r_refdef.view.colorscale = oldcolorscale;
6112 R_ResetViewRendering3D();
6114 R_ClearScreen(r_refdef.fogenabled);
6115 if (r_timereport_active)
6116 R_TimeReport("viewclear");
6119 static void R_BlendView(void)
6121 unsigned int permutation;
6122 float uservecs[4][4];
6124 switch (vid.renderpath)
6126 case RENDERPATH_GL20:
6127 case RENDERPATH_D3D9:
6128 case RENDERPATH_D3D10:
6129 case RENDERPATH_D3D11:
6130 case RENDERPATH_SOFT:
6131 case RENDERPATH_GLES2:
6133 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6134 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6135 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6136 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6137 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6139 if (r_bloomstate.texture_screen)
6141 // make sure the buffer is available
6142 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6144 R_ResetViewRendering2D();
6145 R_Mesh_SetMainRenderTargets();
6147 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6149 // declare variables
6151 static float avgspeed;
6153 speed = VectorLength(cl.movement_velocity);
6155 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6156 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6158 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6159 speed = bound(0, speed, 1);
6160 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6162 // calculate values into a standard alpha
6163 cl.motionbluralpha = 1 - exp(-
6165 (r_motionblur.value * speed / 80)
6167 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6170 max(0.0001, cl.time - cl.oldtime) // fps independent
6173 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6174 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6176 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6178 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6179 GL_Color(1, 1, 1, cl.motionbluralpha);
6180 switch(vid.renderpath)
6182 case RENDERPATH_GL11:
6183 case RENDERPATH_GL13:
6184 case RENDERPATH_GL20:
6185 case RENDERPATH_GLES1:
6186 case RENDERPATH_GLES2:
6187 case RENDERPATH_SOFT:
6188 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6190 case RENDERPATH_D3D9:
6191 case RENDERPATH_D3D10:
6192 case RENDERPATH_D3D11:
6193 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6196 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6197 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6198 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6202 // copy view into the screen texture
6203 R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6204 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6206 else if (!r_bloomstate.texture_bloom)
6208 // we may still have to do view tint...
6209 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6211 // apply a color tint to the whole view
6212 R_ResetViewRendering2D();
6213 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6214 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6215 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6216 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6217 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6219 break; // no screen processing, no bloom, skip it
6222 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6224 // render simple bloom effect
6225 // copy the screen and shrink it and darken it for the bloom process
6226 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6227 // make the bloom texture
6228 R_Bloom_MakeTexture();
6231 #if _MSC_VER >= 1400
6232 #define sscanf sscanf_s
6234 memset(uservecs, 0, sizeof(uservecs));
6235 if (r_glsl_postprocess_uservec1_enable.integer)
6236 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6237 if (r_glsl_postprocess_uservec2_enable.integer)
6238 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6239 if (r_glsl_postprocess_uservec3_enable.integer)
6240 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6241 if (r_glsl_postprocess_uservec4_enable.integer)
6242 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6244 R_ResetViewRendering2D();
6245 GL_Color(1, 1, 1, 1);
6246 GL_BlendFunc(GL_ONE, GL_ZERO);
6248 switch(vid.renderpath)
6250 case RENDERPATH_GL20:
6251 case RENDERPATH_GLES2:
6252 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6253 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6254 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6255 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6256 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6257 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]);
6258 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6259 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]);
6260 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]);
6261 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]);
6262 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]);
6263 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6264 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6265 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);
6267 case RENDERPATH_D3D9:
6269 // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6270 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6271 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6272 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6273 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6274 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6275 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6276 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6277 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6278 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6279 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6280 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6281 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6282 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6283 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6286 case RENDERPATH_D3D10:
6287 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6289 case RENDERPATH_D3D11:
6290 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6292 case RENDERPATH_SOFT:
6293 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6294 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6295 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6296 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6297 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6298 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6299 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6300 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6301 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6302 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6303 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6304 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6305 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6306 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6311 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6312 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6314 case RENDERPATH_GL11:
6315 case RENDERPATH_GL13:
6316 case RENDERPATH_GLES1:
6317 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6319 // apply a color tint to the whole view
6320 R_ResetViewRendering2D();
6321 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6322 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6323 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6324 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6331 matrix4x4_t r_waterscrollmatrix;
6333 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6335 if (r_refdef.fog_density)
6337 r_refdef.fogcolor[0] = r_refdef.fog_red;
6338 r_refdef.fogcolor[1] = r_refdef.fog_green;
6339 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6341 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6342 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6343 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6344 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6348 VectorCopy(r_refdef.fogcolor, fogvec);
6349 // color.rgb *= ContrastBoost * SceneBrightness;
6350 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6351 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6352 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6353 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6358 void R_UpdateVariables(void)
6362 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6364 r_refdef.farclip = r_farclip_base.value;
6365 if (r_refdef.scene.worldmodel)
6366 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6367 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6369 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6370 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6371 r_refdef.polygonfactor = 0;
6372 r_refdef.polygonoffset = 0;
6373 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6374 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6376 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6377 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6378 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6379 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6380 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6381 if (FAKELIGHT_ENABLED)
6383 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6385 if (r_showsurfaces.integer)
6387 r_refdef.scene.rtworld = false;
6388 r_refdef.scene.rtworldshadows = false;
6389 r_refdef.scene.rtdlight = false;
6390 r_refdef.scene.rtdlightshadows = false;
6391 r_refdef.lightmapintensity = 0;
6394 if (gamemode == GAME_NEHAHRA)
6396 if (gl_fogenable.integer)
6398 r_refdef.oldgl_fogenable = true;
6399 r_refdef.fog_density = gl_fogdensity.value;
6400 r_refdef.fog_red = gl_fogred.value;
6401 r_refdef.fog_green = gl_foggreen.value;
6402 r_refdef.fog_blue = gl_fogblue.value;
6403 r_refdef.fog_alpha = 1;
6404 r_refdef.fog_start = 0;
6405 r_refdef.fog_end = gl_skyclip.value;
6406 r_refdef.fog_height = 1<<30;
6407 r_refdef.fog_fadedepth = 128;
6409 else if (r_refdef.oldgl_fogenable)
6411 r_refdef.oldgl_fogenable = false;
6412 r_refdef.fog_density = 0;
6413 r_refdef.fog_red = 0;
6414 r_refdef.fog_green = 0;
6415 r_refdef.fog_blue = 0;
6416 r_refdef.fog_alpha = 0;
6417 r_refdef.fog_start = 0;
6418 r_refdef.fog_end = 0;
6419 r_refdef.fog_height = 1<<30;
6420 r_refdef.fog_fadedepth = 128;
6424 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6425 r_refdef.fog_start = max(0, r_refdef.fog_start);
6426 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6428 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6430 if (r_refdef.fog_density && r_drawfog.integer)
6432 r_refdef.fogenabled = true;
6433 // this is the point where the fog reaches 0.9986 alpha, which we
6434 // consider a good enough cutoff point for the texture
6435 // (0.9986 * 256 == 255.6)
6436 if (r_fog_exp2.integer)
6437 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6439 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6440 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6441 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6442 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6443 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6444 R_BuildFogHeightTexture();
6445 // fog color was already set
6446 // update the fog texture
6447 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)
6448 R_BuildFogTexture();
6449 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6450 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6453 r_refdef.fogenabled = false;
6455 switch(vid.renderpath)
6457 case RENDERPATH_GL20:
6458 case RENDERPATH_D3D9:
6459 case RENDERPATH_D3D10:
6460 case RENDERPATH_D3D11:
6461 case RENDERPATH_SOFT:
6462 case RENDERPATH_GLES2:
6463 if(v_glslgamma.integer && !vid_gammatables_trivial)
6465 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6467 // build GLSL gamma texture
6468 #define RAMPWIDTH 256
6469 unsigned short ramp[RAMPWIDTH * 3];
6470 unsigned char rampbgr[RAMPWIDTH][4];
6473 r_texture_gammaramps_serial = vid_gammatables_serial;
6475 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6476 for(i = 0; i < RAMPWIDTH; ++i)
6478 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6479 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6480 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6483 if (r_texture_gammaramps)
6485 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6489 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6495 // remove GLSL gamma texture
6498 case RENDERPATH_GL11:
6499 case RENDERPATH_GL13:
6500 case RENDERPATH_GLES1:
6505 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6506 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6512 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6513 if( scenetype != r_currentscenetype ) {
6514 // store the old scenetype
6515 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6516 r_currentscenetype = scenetype;
6517 // move in the new scene
6518 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6527 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6529 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6530 if( scenetype == r_currentscenetype ) {
6531 return &r_refdef.scene;
6533 return &r_scenes_store[ scenetype ];
6542 int dpsoftrast_test;
6543 void R_RenderView(void)
6545 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6547 dpsoftrast_test = r_test.integer;
6549 if (r_timereport_active)
6550 R_TimeReport("start");
6551 r_textureframe++; // used only by R_GetCurrentTexture
6552 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6554 if(R_CompileShader_CheckStaticParms())
6557 if (!r_drawentities.integer)
6558 r_refdef.scene.numentities = 0;
6560 R_AnimCache_ClearCache();
6561 R_FrameData_NewFrame();
6563 /* adjust for stereo display */
6564 if(R_Stereo_Active())
6566 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);
6567 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6570 if (r_refdef.view.isoverlay)
6572 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6573 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6574 R_TimeReport("depthclear");
6576 r_refdef.view.showdebug = false;
6578 r_waterstate.enabled = false;
6579 r_waterstate.numwaterplanes = 0;
6583 r_refdef.view.matrix = originalmatrix;
6589 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6591 r_refdef.view.matrix = originalmatrix;
6592 return; //Host_Error ("R_RenderView: NULL worldmodel");
6595 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6597 R_RenderView_UpdateViewVectors();
6599 R_Shadow_UpdateWorldLightSelection();
6601 R_Bloom_StartFrame();
6602 R_Water_StartFrame();
6605 if (r_timereport_active)
6606 R_TimeReport("viewsetup");
6608 R_ResetViewRendering3D();
6610 if (r_refdef.view.clear || r_refdef.fogenabled)
6612 R_ClearScreen(r_refdef.fogenabled);
6613 if (r_timereport_active)
6614 R_TimeReport("viewclear");
6616 r_refdef.view.clear = true;
6618 // this produces a bloom texture to be used in R_BlendView() later
6619 if (r_bloomstate.hdr)
6621 R_HDR_RenderBloomTexture();
6622 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6623 r_textureframe++; // used only by R_GetCurrentTexture
6626 r_refdef.view.showdebug = true;
6629 if (r_timereport_active)
6630 R_TimeReport("visibility");
6632 r_waterstate.numwaterplanes = 0;
6633 if (r_waterstate.enabled)
6634 R_RenderWaterPlanes();
6637 r_waterstate.numwaterplanes = 0;
6640 if (r_timereport_active)
6641 R_TimeReport("blendview");
6643 GL_Scissor(0, 0, vid.width, vid.height);
6644 GL_ScissorTest(false);
6646 r_refdef.view.matrix = originalmatrix;
6651 void R_RenderWaterPlanes(void)
6653 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6655 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6656 if (r_timereport_active)
6657 R_TimeReport("waterworld");
6660 // don't let sound skip if going slow
6661 if (r_refdef.scene.extraupdate)
6664 R_DrawModelsAddWaterPlanes();
6665 if (r_timereport_active)
6666 R_TimeReport("watermodels");
6668 if (r_waterstate.numwaterplanes)
6670 R_Water_ProcessPlanes();
6671 if (r_timereport_active)
6672 R_TimeReport("waterscenes");
6676 extern void R_DrawLightningBeams (void);
6677 extern void VM_CL_AddPolygonsToMeshQueue (void);
6678 extern void R_DrawPortals (void);
6679 extern cvar_t cl_locs_show;
6680 static void R_DrawLocs(void);
6681 static void R_DrawEntityBBoxes(void);
6682 static void R_DrawModelDecals(void);
6683 extern void R_DrawModelShadows(void);
6684 extern void R_DrawModelShadowMaps(void);
6685 extern cvar_t cl_decals_newsystem;
6686 extern qboolean r_shadow_usingdeferredprepass;
6687 void R_RenderScene(void)
6689 qboolean shadowmapping = false;
6691 if (r_timereport_active)
6692 R_TimeReport("beginscene");
6694 r_refdef.stats.renders++;
6698 // don't let sound skip if going slow
6699 if (r_refdef.scene.extraupdate)
6702 R_MeshQueue_BeginScene();
6706 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);
6708 if (r_timereport_active)
6709 R_TimeReport("skystartframe");
6711 if (cl.csqc_vidvars.drawworld)
6713 // don't let sound skip if going slow
6714 if (r_refdef.scene.extraupdate)
6717 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6719 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6720 if (r_timereport_active)
6721 R_TimeReport("worldsky");
6724 if (R_DrawBrushModelsSky() && r_timereport_active)
6725 R_TimeReport("bmodelsky");
6727 if (skyrendermasked && skyrenderlater)
6729 // we have to force off the water clipping plane while rendering sky
6733 if (r_timereport_active)
6734 R_TimeReport("sky");
6738 R_AnimCache_CacheVisibleEntities();
6739 if (r_timereport_active)
6740 R_TimeReport("animation");
6742 R_Shadow_PrepareLights();
6743 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6744 R_Shadow_PrepareModelShadows();
6745 if (r_timereport_active)
6746 R_TimeReport("preparelights");
6748 if (R_Shadow_ShadowMappingEnabled())
6749 shadowmapping = true;
6751 if (r_shadow_usingdeferredprepass)
6752 R_Shadow_DrawPrepass();
6754 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6756 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6757 if (r_timereport_active)
6758 R_TimeReport("worlddepth");
6760 if (r_depthfirst.integer >= 2)
6762 R_DrawModelsDepth();
6763 if (r_timereport_active)
6764 R_TimeReport("modeldepth");
6767 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6769 R_DrawModelShadowMaps();
6770 R_ResetViewRendering3D();
6771 // don't let sound skip if going slow
6772 if (r_refdef.scene.extraupdate)
6776 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6778 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6779 if (r_timereport_active)
6780 R_TimeReport("world");
6783 // don't let sound skip if going slow
6784 if (r_refdef.scene.extraupdate)
6788 if (r_timereport_active)
6789 R_TimeReport("models");
6791 // don't let sound skip if going slow
6792 if (r_refdef.scene.extraupdate)
6795 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6797 R_DrawModelShadows();
6798 R_ResetViewRendering3D();
6799 // don't let sound skip if going slow
6800 if (r_refdef.scene.extraupdate)
6804 if (!r_shadow_usingdeferredprepass)
6806 R_Shadow_DrawLights();
6807 if (r_timereport_active)
6808 R_TimeReport("rtlights");
6811 // don't let sound skip if going slow
6812 if (r_refdef.scene.extraupdate)
6815 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6817 R_DrawModelShadows();
6818 R_ResetViewRendering3D();
6819 // don't let sound skip if going slow
6820 if (r_refdef.scene.extraupdate)
6824 if (cl.csqc_vidvars.drawworld)
6826 if (cl_decals_newsystem.integer)
6828 R_DrawModelDecals();
6829 if (r_timereport_active)
6830 R_TimeReport("modeldecals");
6835 if (r_timereport_active)
6836 R_TimeReport("decals");
6840 if (r_timereport_active)
6841 R_TimeReport("particles");
6844 if (r_timereport_active)
6845 R_TimeReport("explosions");
6847 R_DrawLightningBeams();
6848 if (r_timereport_active)
6849 R_TimeReport("lightning");
6852 VM_CL_AddPolygonsToMeshQueue();
6854 if (r_refdef.view.showdebug)
6856 if (cl_locs_show.integer)
6859 if (r_timereport_active)
6860 R_TimeReport("showlocs");
6863 if (r_drawportals.integer)
6866 if (r_timereport_active)
6867 R_TimeReport("portals");
6870 if (r_showbboxes.value > 0)
6872 R_DrawEntityBBoxes();
6873 if (r_timereport_active)
6874 R_TimeReport("bboxes");
6878 if (r_transparent.integer)
6880 R_MeshQueue_RenderTransparent();
6881 if (r_timereport_active)
6882 R_TimeReport("drawtrans");
6885 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))
6887 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6888 if (r_timereport_active)
6889 R_TimeReport("worlddebug");
6890 R_DrawModelsDebug();
6891 if (r_timereport_active)
6892 R_TimeReport("modeldebug");
6895 if (cl.csqc_vidvars.drawworld)
6897 R_Shadow_DrawCoronas();
6898 if (r_timereport_active)
6899 R_TimeReport("coronas");
6904 GL_DepthTest(false);
6905 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6906 GL_Color(1, 1, 1, 1);
6907 qglBegin(GL_POLYGON);
6908 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6909 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6910 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6911 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6913 qglBegin(GL_POLYGON);
6914 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]);
6915 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]);
6916 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]);
6917 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]);
6919 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6923 // don't let sound skip if going slow
6924 if (r_refdef.scene.extraupdate)
6927 R_ResetViewRendering2D();
6930 static const unsigned short bboxelements[36] =
6940 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6943 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6945 RSurf_ActiveWorldEntity();
6947 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6948 GL_DepthMask(false);
6949 GL_DepthRange(0, 1);
6950 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6951 // R_Mesh_ResetTextureState();
6953 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6954 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6955 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6956 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6957 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6958 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6959 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6960 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6961 R_FillColors(color4f, 8, cr, cg, cb, ca);
6962 if (r_refdef.fogenabled)
6964 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6966 f1 = RSurf_FogVertex(v);
6968 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6969 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6970 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6973 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6974 R_Mesh_ResetTextureState();
6975 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6976 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6979 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6983 prvm_edict_t *edict;
6984 prvm_prog_t *prog_save = prog;
6986 // this function draws bounding boxes of server entities
6990 GL_CullFace(GL_NONE);
6991 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6995 for (i = 0;i < numsurfaces;i++)
6997 edict = PRVM_EDICT_NUM(surfacelist[i]);
6998 switch ((int)edict->fields.server->solid)
7000 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
7001 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
7002 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
7003 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7004 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
7005 default: Vector4Set(color, 0, 0, 0, 0.50);break;
7007 color[3] *= r_showbboxes.value;
7008 color[3] = bound(0, color[3], 1);
7009 GL_DepthTest(!r_showdisabledepthtest.integer);
7010 GL_CullFace(r_refdef.view.cullface_front);
7011 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7017 static void R_DrawEntityBBoxes(void)
7020 prvm_edict_t *edict;
7022 prvm_prog_t *prog_save = prog;
7024 // this function draws bounding boxes of server entities
7030 for (i = 0;i < prog->num_edicts;i++)
7032 edict = PRVM_EDICT_NUM(i);
7033 if (edict->priv.server->free)
7035 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7036 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7038 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7040 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7041 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7047 static const int nomodelelement3i[24] =
7059 static const unsigned short nomodelelement3s[24] =
7071 static const float nomodelvertex3f[6*3] =
7081 static const float nomodelcolor4f[6*4] =
7083 0.0f, 0.0f, 0.5f, 1.0f,
7084 0.0f, 0.0f, 0.5f, 1.0f,
7085 0.0f, 0.5f, 0.0f, 1.0f,
7086 0.0f, 0.5f, 0.0f, 1.0f,
7087 0.5f, 0.0f, 0.0f, 1.0f,
7088 0.5f, 0.0f, 0.0f, 1.0f
7091 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7097 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);
7099 // this is only called once per entity so numsurfaces is always 1, and
7100 // surfacelist is always {0}, so this code does not handle batches
7102 if (rsurface.ent_flags & RENDER_ADDITIVE)
7104 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7105 GL_DepthMask(false);
7107 else if (rsurface.colormod[3] < 1)
7109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7110 GL_DepthMask(false);
7114 GL_BlendFunc(GL_ONE, GL_ZERO);
7117 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7118 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7119 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7120 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7121 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7122 for (i = 0, c = color4f;i < 6;i++, c += 4)
7124 c[0] *= rsurface.colormod[0];
7125 c[1] *= rsurface.colormod[1];
7126 c[2] *= rsurface.colormod[2];
7127 c[3] *= rsurface.colormod[3];
7129 if (r_refdef.fogenabled)
7131 for (i = 0, c = color4f;i < 6;i++, c += 4)
7133 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7135 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7136 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7137 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7140 // R_Mesh_ResetTextureState();
7141 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7142 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7143 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7146 void R_DrawNoModel(entity_render_t *ent)
7149 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7150 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7151 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7153 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7156 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7158 vec3_t right1, right2, diff, normal;
7160 VectorSubtract (org2, org1, normal);
7162 // calculate 'right' vector for start
7163 VectorSubtract (r_refdef.view.origin, org1, diff);
7164 CrossProduct (normal, diff, right1);
7165 VectorNormalize (right1);
7167 // calculate 'right' vector for end
7168 VectorSubtract (r_refdef.view.origin, org2, diff);
7169 CrossProduct (normal, diff, right2);
7170 VectorNormalize (right2);
7172 vert[ 0] = org1[0] + width * right1[0];
7173 vert[ 1] = org1[1] + width * right1[1];
7174 vert[ 2] = org1[2] + width * right1[2];
7175 vert[ 3] = org1[0] - width * right1[0];
7176 vert[ 4] = org1[1] - width * right1[1];
7177 vert[ 5] = org1[2] - width * right1[2];
7178 vert[ 6] = org2[0] - width * right2[0];
7179 vert[ 7] = org2[1] - width * right2[1];
7180 vert[ 8] = org2[2] - width * right2[2];
7181 vert[ 9] = org2[0] + width * right2[0];
7182 vert[10] = org2[1] + width * right2[1];
7183 vert[11] = org2[2] + width * right2[2];
7186 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)
7188 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7189 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7190 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7191 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7192 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7193 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7194 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7195 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7196 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7197 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7198 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7199 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7202 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7207 VectorSet(v, x, y, z);
7208 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7209 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7211 if (i == mesh->numvertices)
7213 if (mesh->numvertices < mesh->maxvertices)
7215 VectorCopy(v, vertex3f);
7216 mesh->numvertices++;
7218 return mesh->numvertices;
7224 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7228 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7229 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7230 e = mesh->element3i + mesh->numtriangles * 3;
7231 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7233 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7234 if (mesh->numtriangles < mesh->maxtriangles)
7239 mesh->numtriangles++;
7241 element[1] = element[2];
7245 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7249 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7250 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7251 e = mesh->element3i + mesh->numtriangles * 3;
7252 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7254 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7255 if (mesh->numtriangles < mesh->maxtriangles)
7260 mesh->numtriangles++;
7262 element[1] = element[2];
7266 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7267 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7269 int planenum, planenum2;
7272 mplane_t *plane, *plane2;
7274 double temppoints[2][256*3];
7275 // figure out how large a bounding box we need to properly compute this brush
7277 for (w = 0;w < numplanes;w++)
7278 maxdist = max(maxdist, fabs(planes[w].dist));
7279 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7280 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7281 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7285 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7286 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7288 if (planenum2 == planenum)
7290 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);
7293 if (tempnumpoints < 3)
7295 // generate elements forming a triangle fan for this polygon
7296 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7300 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)
7302 texturelayer_t *layer;
7303 layer = t->currentlayers + t->currentnumlayers++;
7305 layer->depthmask = depthmask;
7306 layer->blendfunc1 = blendfunc1;
7307 layer->blendfunc2 = blendfunc2;
7308 layer->texture = texture;
7309 layer->texmatrix = *matrix;
7310 layer->color[0] = r;
7311 layer->color[1] = g;
7312 layer->color[2] = b;
7313 layer->color[3] = a;
7316 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7318 if(parms[0] == 0 && parms[1] == 0)
7320 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7321 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7326 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7329 index = parms[2] + r_refdef.scene.time * parms[3];
7330 index -= floor(index);
7331 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7334 case Q3WAVEFUNC_NONE:
7335 case Q3WAVEFUNC_NOISE:
7336 case Q3WAVEFUNC_COUNT:
7339 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7340 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7341 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7342 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7343 case Q3WAVEFUNC_TRIANGLE:
7345 f = index - floor(index);
7356 f = parms[0] + parms[1] * f;
7357 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7358 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7362 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7367 matrix4x4_t matrix, temp;
7368 switch(tcmod->tcmod)
7372 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7373 matrix = r_waterscrollmatrix;
7375 matrix = identitymatrix;
7377 case Q3TCMOD_ENTITYTRANSLATE:
7378 // this is used in Q3 to allow the gamecode to control texcoord
7379 // scrolling on the entity, which is not supported in darkplaces yet.
7380 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7382 case Q3TCMOD_ROTATE:
7383 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7384 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7385 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7388 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7390 case Q3TCMOD_SCROLL:
7391 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7393 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7394 w = (int) tcmod->parms[0];
7395 h = (int) tcmod->parms[1];
7396 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7398 idx = (int) floor(f * w * h);
7399 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7401 case Q3TCMOD_STRETCH:
7402 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7403 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7405 case Q3TCMOD_TRANSFORM:
7406 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7407 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7408 VectorSet(tcmat + 6, 0 , 0 , 1);
7409 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7410 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7412 case Q3TCMOD_TURBULENT:
7413 // this is handled in the RSurf_PrepareVertices function
7414 matrix = identitymatrix;
7418 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7421 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7423 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7424 char name[MAX_QPATH];
7425 skinframe_t *skinframe;
7426 unsigned char pixels[296*194];
7427 strlcpy(cache->name, skinname, sizeof(cache->name));
7428 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7429 if (developer_loading.integer)
7430 Con_Printf("loading %s\n", name);
7431 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7432 if (!skinframe || !skinframe->base)
7435 fs_offset_t filesize;
7437 f = FS_LoadFile(name, tempmempool, true, &filesize);
7440 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7441 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7445 cache->skinframe = skinframe;
7448 texture_t *R_GetCurrentTexture(texture_t *t)
7451 const entity_render_t *ent = rsurface.entity;
7452 dp_model_t *model = ent->model;
7453 q3shaderinfo_layer_tcmod_t *tcmod;
7455 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7456 return t->currentframe;
7457 t->update_lastrenderframe = r_textureframe;
7458 t->update_lastrenderentity = (void *)ent;
7460 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7461 t->camera_entity = ent->entitynumber;
7463 t->camera_entity = 0;
7465 // switch to an alternate material if this is a q1bsp animated material
7467 texture_t *texture = t;
7468 int s = rsurface.ent_skinnum;
7469 if ((unsigned int)s >= (unsigned int)model->numskins)
7471 if (model->skinscenes)
7473 if (model->skinscenes[s].framecount > 1)
7474 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7476 s = model->skinscenes[s].firstframe;
7479 t = t + s * model->num_surfaces;
7482 // use an alternate animation if the entity's frame is not 0,
7483 // and only if the texture has an alternate animation
7484 if (rsurface.ent_alttextures && t->anim_total[1])
7485 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7487 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7489 texture->currentframe = t;
7492 // update currentskinframe to be a qw skin or animation frame
7493 if (rsurface.ent_qwskin >= 0)
7495 i = rsurface.ent_qwskin;
7496 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7498 r_qwskincache_size = cl.maxclients;
7500 Mem_Free(r_qwskincache);
7501 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7503 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7504 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7505 t->currentskinframe = r_qwskincache[i].skinframe;
7506 if (t->currentskinframe == NULL)
7507 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7509 else if (t->numskinframes >= 2)
7510 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7511 if (t->backgroundnumskinframes >= 2)
7512 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7514 t->currentmaterialflags = t->basematerialflags;
7515 t->currentalpha = rsurface.colormod[3];
7516 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7517 t->currentalpha *= r_wateralpha.value;
7518 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7519 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7520 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7521 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7522 if (!(rsurface.ent_flags & RENDER_LIGHT))
7523 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7524 else if (FAKELIGHT_ENABLED)
7526 // no modellight if using fakelight for the map
7528 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7530 // pick a model lighting mode
7531 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7532 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7534 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7536 if (rsurface.ent_flags & RENDER_ADDITIVE)
7537 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7538 else if (t->currentalpha < 1)
7539 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7540 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7541 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7542 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7543 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7544 if (t->backgroundnumskinframes)
7545 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7546 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7548 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7549 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7552 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7553 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7554 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7556 // there is no tcmod
7557 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7559 t->currenttexmatrix = r_waterscrollmatrix;
7560 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7562 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7564 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7565 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7568 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7569 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7570 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7571 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7573 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7574 if (t->currentskinframe->qpixels)
7575 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7576 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7577 if (!t->basetexture)
7578 t->basetexture = r_texture_notexture;
7579 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7580 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7581 t->nmaptexture = t->currentskinframe->nmap;
7582 if (!t->nmaptexture)
7583 t->nmaptexture = r_texture_blanknormalmap;
7584 t->glosstexture = r_texture_black;
7585 t->glowtexture = t->currentskinframe->glow;
7586 t->fogtexture = t->currentskinframe->fog;
7587 t->reflectmasktexture = t->currentskinframe->reflect;
7588 if (t->backgroundnumskinframes)
7590 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7591 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7592 t->backgroundglosstexture = r_texture_black;
7593 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7594 if (!t->backgroundnmaptexture)
7595 t->backgroundnmaptexture = r_texture_blanknormalmap;
7599 t->backgroundbasetexture = r_texture_white;
7600 t->backgroundnmaptexture = r_texture_blanknormalmap;
7601 t->backgroundglosstexture = r_texture_black;
7602 t->backgroundglowtexture = NULL;
7604 t->specularpower = r_shadow_glossexponent.value;
7605 // TODO: store reference values for these in the texture?
7606 t->specularscale = 0;
7607 if (r_shadow_gloss.integer > 0)
7609 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7611 if (r_shadow_glossintensity.value > 0)
7613 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7614 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7615 t->specularscale = r_shadow_glossintensity.value;
7618 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7620 t->glosstexture = r_texture_white;
7621 t->backgroundglosstexture = r_texture_white;
7622 t->specularscale = r_shadow_gloss2intensity.value;
7623 t->specularpower = r_shadow_gloss2exponent.value;
7626 t->specularscale *= t->specularscalemod;
7627 t->specularpower *= t->specularpowermod;
7629 // lightmaps mode looks bad with dlights using actual texturing, so turn
7630 // off the colormap and glossmap, but leave the normalmap on as it still
7631 // accurately represents the shading involved
7632 if (gl_lightmaps.integer)
7634 t->basetexture = r_texture_grey128;
7635 t->pantstexture = r_texture_black;
7636 t->shirttexture = r_texture_black;
7637 t->nmaptexture = r_texture_blanknormalmap;
7638 t->glosstexture = r_texture_black;
7639 t->glowtexture = NULL;
7640 t->fogtexture = NULL;
7641 t->reflectmasktexture = NULL;
7642 t->backgroundbasetexture = NULL;
7643 t->backgroundnmaptexture = r_texture_blanknormalmap;
7644 t->backgroundglosstexture = r_texture_black;
7645 t->backgroundglowtexture = NULL;
7646 t->specularscale = 0;
7647 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7650 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7651 VectorClear(t->dlightcolor);
7652 t->currentnumlayers = 0;
7653 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7655 int blendfunc1, blendfunc2;
7657 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7659 blendfunc1 = GL_SRC_ALPHA;
7660 blendfunc2 = GL_ONE;
7662 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7664 blendfunc1 = GL_SRC_ALPHA;
7665 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7667 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7669 blendfunc1 = t->customblendfunc[0];
7670 blendfunc2 = t->customblendfunc[1];
7674 blendfunc1 = GL_ONE;
7675 blendfunc2 = GL_ZERO;
7677 // don't colormod evilblend textures
7678 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7679 VectorSet(t->lightmapcolor, 1, 1, 1);
7680 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7681 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7683 // fullbright is not affected by r_refdef.lightmapintensity
7684 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
7685 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7686 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7687 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7688 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7692 vec3_t ambientcolor;
7694 // set the color tint used for lights affecting this surface
7695 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7697 // q3bsp has no lightmap updates, so the lightstylevalue that
7698 // would normally be baked into the lightmap must be
7699 // applied to the color
7700 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7701 if (model->type == mod_brushq3)
7702 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7703 colorscale *= r_refdef.lightmapintensity;
7704 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7705 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7706 // basic lit geometry
7707 R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
7708 // add pants/shirt if needed
7709 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7710 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7711 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7712 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
7713 // now add ambient passes if needed
7714 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7716 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
7717 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7718 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7719 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7720 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7723 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7724 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
7725 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7727 // if this is opaque use alpha blend which will darken the earlier
7730 // if this is an alpha blended material, all the earlier passes
7731 // were darkened by fog already, so we only need to add the fog
7732 // color ontop through the fog mask texture
7734 // if this is an additive blended material, all the earlier passes
7735 // were darkened by fog already, and we should not add fog color
7736 // (because the background was not darkened, there is no fog color
7737 // that was lost behind it).
7738 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
7742 return t->currentframe;
7745 rsurfacestate_t rsurface;
7747 void RSurf_ActiveWorldEntity(void)
7749 dp_model_t *model = r_refdef.scene.worldmodel;
7750 //if (rsurface.entity == r_refdef.scene.worldentity)
7752 rsurface.entity = r_refdef.scene.worldentity;
7753 rsurface.skeleton = NULL;
7754 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7755 rsurface.ent_skinnum = 0;
7756 rsurface.ent_qwskin = -1;
7757 rsurface.ent_shadertime = 0;
7758 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7759 rsurface.matrix = identitymatrix;
7760 rsurface.inversematrix = identitymatrix;
7761 rsurface.matrixscale = 1;
7762 rsurface.inversematrixscale = 1;
7763 R_EntityMatrix(&identitymatrix);
7764 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7765 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7766 rsurface.fograngerecip = r_refdef.fograngerecip;
7767 rsurface.fogheightfade = r_refdef.fogheightfade;
7768 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7769 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7770 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7771 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7772 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7773 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7774 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7775 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7776 rsurface.colormod[3] = 1;
7777 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
7778 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7779 rsurface.frameblend[0].lerp = 1;
7780 rsurface.ent_alttextures = false;
7781 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7782 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7783 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7784 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7785 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7786 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7787 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7788 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7789 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7790 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7791 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7792 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7793 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7794 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7795 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7796 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7797 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7798 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7799 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7801 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7802 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7804 rsurface.modelelement3i = model->surfmesh.data_element3i;
7805 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7806 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7807 rsurface.modelelement3s = model->surfmesh.data_element3s;
7808 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7809 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7810 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7811 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7812 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7813 rsurface.modelsurfaces = model->data_surfaces;
7814 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7815 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7816 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7817 rsurface.modelgeneratedvertex = false;
7818 rsurface.batchgeneratedvertex = false;
7819 rsurface.batchfirstvertex = 0;
7820 rsurface.batchnumvertices = 0;
7821 rsurface.batchfirsttriangle = 0;
7822 rsurface.batchnumtriangles = 0;
7823 rsurface.batchvertex3f = NULL;
7824 rsurface.batchvertex3f_vertexbuffer = NULL;
7825 rsurface.batchvertex3f_bufferoffset = 0;
7826 rsurface.batchsvector3f = NULL;
7827 rsurface.batchsvector3f_vertexbuffer = NULL;
7828 rsurface.batchsvector3f_bufferoffset = 0;
7829 rsurface.batchtvector3f = NULL;
7830 rsurface.batchtvector3f_vertexbuffer = NULL;
7831 rsurface.batchtvector3f_bufferoffset = 0;
7832 rsurface.batchnormal3f = NULL;
7833 rsurface.batchnormal3f_vertexbuffer = NULL;
7834 rsurface.batchnormal3f_bufferoffset = 0;
7835 rsurface.batchlightmapcolor4f = NULL;
7836 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7837 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7838 rsurface.batchtexcoordtexture2f = NULL;
7839 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7840 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7841 rsurface.batchtexcoordlightmap2f = NULL;
7842 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7843 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7844 rsurface.batchvertexmesh = NULL;
7845 rsurface.batchvertexmeshbuffer = NULL;
7846 rsurface.batchvertex3fbuffer = NULL;
7847 rsurface.batchelement3i = NULL;
7848 rsurface.batchelement3i_indexbuffer = NULL;
7849 rsurface.batchelement3i_bufferoffset = 0;
7850 rsurface.batchelement3s = NULL;
7851 rsurface.batchelement3s_indexbuffer = NULL;
7852 rsurface.batchelement3s_bufferoffset = 0;
7853 rsurface.passcolor4f = NULL;
7854 rsurface.passcolor4f_vertexbuffer = NULL;
7855 rsurface.passcolor4f_bufferoffset = 0;
7858 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7860 dp_model_t *model = ent->model;
7861 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7863 rsurface.entity = (entity_render_t *)ent;
7864 rsurface.skeleton = ent->skeleton;
7865 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7866 rsurface.ent_skinnum = ent->skinnum;
7867 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;
7868 rsurface.ent_shadertime = ent->shadertime;
7869 rsurface.ent_flags = ent->flags;
7870 rsurface.matrix = ent->matrix;
7871 rsurface.inversematrix = ent->inversematrix;
7872 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7873 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7874 R_EntityMatrix(&rsurface.matrix);
7875 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7876 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7877 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7878 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7879 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7880 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7881 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7882 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7883 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7884 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7885 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7886 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7887 rsurface.colormod[3] = ent->alpha;
7888 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7889 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7890 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7891 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7892 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7893 if (ent->model->brush.submodel && !prepass)
7895 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7896 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7898 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7900 if (ent->animcache_vertex3f)
7902 rsurface.modelvertex3f = ent->animcache_vertex3f;
7903 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7904 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7905 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7906 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7907 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7908 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7910 else if (wanttangents)
7912 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7913 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7914 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7915 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7916 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7917 rsurface.modelvertexmesh = NULL;
7918 rsurface.modelvertexmeshbuffer = NULL;
7919 rsurface.modelvertex3fbuffer = NULL;
7921 else if (wantnormals)
7923 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7924 rsurface.modelsvector3f = NULL;
7925 rsurface.modeltvector3f = NULL;
7926 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7927 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7928 rsurface.modelvertexmesh = NULL;
7929 rsurface.modelvertexmeshbuffer = NULL;
7930 rsurface.modelvertex3fbuffer = NULL;
7934 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7935 rsurface.modelsvector3f = NULL;
7936 rsurface.modeltvector3f = NULL;
7937 rsurface.modelnormal3f = NULL;
7938 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7939 rsurface.modelvertexmesh = NULL;
7940 rsurface.modelvertexmeshbuffer = NULL;
7941 rsurface.modelvertex3fbuffer = NULL;
7943 rsurface.modelvertex3f_vertexbuffer = 0;
7944 rsurface.modelvertex3f_bufferoffset = 0;
7945 rsurface.modelsvector3f_vertexbuffer = 0;
7946 rsurface.modelsvector3f_bufferoffset = 0;
7947 rsurface.modeltvector3f_vertexbuffer = 0;
7948 rsurface.modeltvector3f_bufferoffset = 0;
7949 rsurface.modelnormal3f_vertexbuffer = 0;
7950 rsurface.modelnormal3f_bufferoffset = 0;
7951 rsurface.modelgeneratedvertex = true;
7955 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7956 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7958 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7959 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7961 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7962 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7964 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7965 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7967 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7968 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7969 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7970 rsurface.modelgeneratedvertex = false;
7972 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7973 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7975 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7976 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7978 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7979 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7981 rsurface.modelelement3i = model->surfmesh.data_element3i;
7982 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7983 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7984 rsurface.modelelement3s = model->surfmesh.data_element3s;
7985 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7986 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7987 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7988 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7989 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7990 rsurface.modelsurfaces = model->data_surfaces;
7991 rsurface.batchgeneratedvertex = false;
7992 rsurface.batchfirstvertex = 0;
7993 rsurface.batchnumvertices = 0;
7994 rsurface.batchfirsttriangle = 0;
7995 rsurface.batchnumtriangles = 0;
7996 rsurface.batchvertex3f = NULL;
7997 rsurface.batchvertex3f_vertexbuffer = NULL;
7998 rsurface.batchvertex3f_bufferoffset = 0;
7999 rsurface.batchsvector3f = NULL;
8000 rsurface.batchsvector3f_vertexbuffer = NULL;
8001 rsurface.batchsvector3f_bufferoffset = 0;
8002 rsurface.batchtvector3f = NULL;
8003 rsurface.batchtvector3f_vertexbuffer = NULL;
8004 rsurface.batchtvector3f_bufferoffset = 0;
8005 rsurface.batchnormal3f = NULL;
8006 rsurface.batchnormal3f_vertexbuffer = NULL;
8007 rsurface.batchnormal3f_bufferoffset = 0;
8008 rsurface.batchlightmapcolor4f = NULL;
8009 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8010 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8011 rsurface.batchtexcoordtexture2f = NULL;
8012 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8013 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8014 rsurface.batchtexcoordlightmap2f = NULL;
8015 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8016 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8017 rsurface.batchvertexmesh = NULL;
8018 rsurface.batchvertexmeshbuffer = NULL;
8019 rsurface.batchvertex3fbuffer = NULL;
8020 rsurface.batchelement3i = NULL;
8021 rsurface.batchelement3i_indexbuffer = NULL;
8022 rsurface.batchelement3i_bufferoffset = 0;
8023 rsurface.batchelement3s = NULL;
8024 rsurface.batchelement3s_indexbuffer = NULL;
8025 rsurface.batchelement3s_bufferoffset = 0;
8026 rsurface.passcolor4f = NULL;
8027 rsurface.passcolor4f_vertexbuffer = NULL;
8028 rsurface.passcolor4f_bufferoffset = 0;
8031 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)
8033 rsurface.entity = r_refdef.scene.worldentity;
8034 rsurface.skeleton = NULL;
8035 rsurface.ent_skinnum = 0;
8036 rsurface.ent_qwskin = -1;
8037 rsurface.ent_shadertime = shadertime;
8038 rsurface.ent_flags = entflags;
8039 rsurface.modelnumvertices = numvertices;
8040 rsurface.modelnumtriangles = numtriangles;
8041 rsurface.matrix = *matrix;
8042 rsurface.inversematrix = *inversematrix;
8043 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8044 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8045 R_EntityMatrix(&rsurface.matrix);
8046 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8047 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8048 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8049 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8050 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8051 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8052 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8053 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8054 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8055 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8056 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8057 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8058 VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8059 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8060 rsurface.frameblend[0].lerp = 1;
8061 rsurface.ent_alttextures = false;
8062 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8063 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8066 rsurface.modelvertex3f = (float *)vertex3f;
8067 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8068 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8069 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8071 else if (wantnormals)
8073 rsurface.modelvertex3f = (float *)vertex3f;
8074 rsurface.modelsvector3f = NULL;
8075 rsurface.modeltvector3f = NULL;
8076 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8080 rsurface.modelvertex3f = (float *)vertex3f;
8081 rsurface.modelsvector3f = NULL;
8082 rsurface.modeltvector3f = NULL;
8083 rsurface.modelnormal3f = NULL;
8085 rsurface.modelvertexmesh = NULL;
8086 rsurface.modelvertexmeshbuffer = NULL;
8087 rsurface.modelvertex3fbuffer = NULL;
8088 rsurface.modelvertex3f_vertexbuffer = 0;
8089 rsurface.modelvertex3f_bufferoffset = 0;
8090 rsurface.modelsvector3f_vertexbuffer = 0;
8091 rsurface.modelsvector3f_bufferoffset = 0;
8092 rsurface.modeltvector3f_vertexbuffer = 0;
8093 rsurface.modeltvector3f_bufferoffset = 0;
8094 rsurface.modelnormal3f_vertexbuffer = 0;
8095 rsurface.modelnormal3f_bufferoffset = 0;
8096 rsurface.modelgeneratedvertex = true;
8097 rsurface.modellightmapcolor4f = (float *)color4f;
8098 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8099 rsurface.modellightmapcolor4f_bufferoffset = 0;
8100 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8101 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8102 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8103 rsurface.modeltexcoordlightmap2f = NULL;
8104 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8105 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8106 rsurface.modelelement3i = (int *)element3i;
8107 rsurface.modelelement3i_indexbuffer = NULL;
8108 rsurface.modelelement3i_bufferoffset = 0;
8109 rsurface.modelelement3s = (unsigned short *)element3s;
8110 rsurface.modelelement3s_indexbuffer = NULL;
8111 rsurface.modelelement3s_bufferoffset = 0;
8112 rsurface.modellightmapoffsets = NULL;
8113 rsurface.modelsurfaces = NULL;
8114 rsurface.batchgeneratedvertex = false;
8115 rsurface.batchfirstvertex = 0;
8116 rsurface.batchnumvertices = 0;
8117 rsurface.batchfirsttriangle = 0;
8118 rsurface.batchnumtriangles = 0;
8119 rsurface.batchvertex3f = NULL;
8120 rsurface.batchvertex3f_vertexbuffer = NULL;
8121 rsurface.batchvertex3f_bufferoffset = 0;
8122 rsurface.batchsvector3f = NULL;
8123 rsurface.batchsvector3f_vertexbuffer = NULL;
8124 rsurface.batchsvector3f_bufferoffset = 0;
8125 rsurface.batchtvector3f = NULL;
8126 rsurface.batchtvector3f_vertexbuffer = NULL;
8127 rsurface.batchtvector3f_bufferoffset = 0;
8128 rsurface.batchnormal3f = NULL;
8129 rsurface.batchnormal3f_vertexbuffer = NULL;
8130 rsurface.batchnormal3f_bufferoffset = 0;
8131 rsurface.batchlightmapcolor4f = NULL;
8132 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8133 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8134 rsurface.batchtexcoordtexture2f = NULL;
8135 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8136 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8137 rsurface.batchtexcoordlightmap2f = NULL;
8138 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8139 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8140 rsurface.batchvertexmesh = NULL;
8141 rsurface.batchvertexmeshbuffer = NULL;
8142 rsurface.batchvertex3fbuffer = NULL;
8143 rsurface.batchelement3i = NULL;
8144 rsurface.batchelement3i_indexbuffer = NULL;
8145 rsurface.batchelement3i_bufferoffset = 0;
8146 rsurface.batchelement3s = NULL;
8147 rsurface.batchelement3s_indexbuffer = NULL;
8148 rsurface.batchelement3s_bufferoffset = 0;
8149 rsurface.passcolor4f = NULL;
8150 rsurface.passcolor4f_vertexbuffer = NULL;
8151 rsurface.passcolor4f_bufferoffset = 0;
8153 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8155 if ((wantnormals || wanttangents) && !normal3f)
8157 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8158 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8160 if (wanttangents && !svector3f)
8162 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8163 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8164 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8169 float RSurf_FogPoint(const float *v)
8171 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8172 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8173 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8174 float FogHeightFade = r_refdef.fogheightfade;
8176 unsigned int fogmasktableindex;
8177 if (r_refdef.fogplaneviewabove)
8178 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8180 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8181 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8182 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8185 float RSurf_FogVertex(const float *v)
8187 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8188 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8189 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8190 float FogHeightFade = rsurface.fogheightfade;
8192 unsigned int fogmasktableindex;
8193 if (r_refdef.fogplaneviewabove)
8194 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8196 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8197 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8198 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8201 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8204 for (i = 0;i < numelements;i++)
8205 outelement3i[i] = inelement3i[i] + adjust;
8208 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8209 extern cvar_t gl_vbo;
8210 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8218 int surfacefirsttriangle;
8219 int surfacenumtriangles;
8220 int surfacefirstvertex;
8221 int surfaceendvertex;
8222 int surfacenumvertices;
8223 int batchnumvertices;
8224 int batchnumtriangles;
8228 qboolean dynamicvertex;
8232 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8234 q3shaderinfo_deform_t *deform;
8235 const msurface_t *surface, *firstsurface;
8236 r_vertexmesh_t *vertexmesh;
8237 if (!texturenumsurfaces)
8239 // find vertex range of this surface batch
8241 firstsurface = texturesurfacelist[0];
8242 firsttriangle = firstsurface->num_firsttriangle;
8243 batchnumvertices = 0;
8244 batchnumtriangles = 0;
8245 firstvertex = endvertex = firstsurface->num_firstvertex;
8246 for (i = 0;i < texturenumsurfaces;i++)
8248 surface = texturesurfacelist[i];
8249 if (surface != firstsurface + i)
8251 surfacefirstvertex = surface->num_firstvertex;
8252 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8253 surfacenumvertices = surface->num_vertices;
8254 surfacenumtriangles = surface->num_triangles;
8255 if (firstvertex > surfacefirstvertex)
8256 firstvertex = surfacefirstvertex;
8257 if (endvertex < surfaceendvertex)
8258 endvertex = surfaceendvertex;
8259 batchnumvertices += surfacenumvertices;
8260 batchnumtriangles += surfacenumtriangles;
8263 // we now know the vertex range used, and if there are any gaps in it
8264 rsurface.batchfirstvertex = firstvertex;
8265 rsurface.batchnumvertices = endvertex - firstvertex;
8266 rsurface.batchfirsttriangle = firsttriangle;
8267 rsurface.batchnumtriangles = batchnumtriangles;
8269 // this variable holds flags for which properties have been updated that
8270 // may require regenerating vertexmesh array...
8273 // check if any dynamic vertex processing must occur
8274 dynamicvertex = false;
8276 // if there is a chance of animated vertex colors, it's a dynamic batch
8277 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8279 dynamicvertex = true;
8280 batchneed |= BATCHNEED_NOGAPS;
8281 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8284 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8286 switch (deform->deform)
8289 case Q3DEFORM_PROJECTIONSHADOW:
8290 case Q3DEFORM_TEXT0:
8291 case Q3DEFORM_TEXT1:
8292 case Q3DEFORM_TEXT2:
8293 case Q3DEFORM_TEXT3:
8294 case Q3DEFORM_TEXT4:
8295 case Q3DEFORM_TEXT5:
8296 case Q3DEFORM_TEXT6:
8297 case Q3DEFORM_TEXT7:
8300 case Q3DEFORM_AUTOSPRITE:
8301 dynamicvertex = true;
8302 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8303 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8305 case Q3DEFORM_AUTOSPRITE2:
8306 dynamicvertex = true;
8307 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8308 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8310 case Q3DEFORM_NORMAL:
8311 dynamicvertex = true;
8312 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8313 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8316 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8317 break; // if wavefunc is a nop, ignore this transform
8318 dynamicvertex = true;
8319 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8320 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8322 case Q3DEFORM_BULGE:
8323 dynamicvertex = true;
8324 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8325 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8328 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8329 break; // if wavefunc is a nop, ignore this transform
8330 dynamicvertex = true;
8331 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8332 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8336 switch(rsurface.texture->tcgen.tcgen)
8339 case Q3TCGEN_TEXTURE:
8341 case Q3TCGEN_LIGHTMAP:
8342 dynamicvertex = true;
8343 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8344 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8346 case Q3TCGEN_VECTOR:
8347 dynamicvertex = true;
8348 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8349 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8351 case Q3TCGEN_ENVIRONMENT:
8352 dynamicvertex = true;
8353 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8354 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8357 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8359 dynamicvertex = true;
8360 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8361 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8364 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8366 dynamicvertex = true;
8367 batchneed |= BATCHNEED_NOGAPS;
8368 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8371 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8373 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8374 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8375 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8376 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8377 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8378 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8379 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8382 // when the model data has no vertex buffer (dynamic mesh), we need to
8384 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8385 batchneed |= BATCHNEED_NOGAPS;
8387 // if needsupdate, we have to do a dynamic vertex batch for sure
8388 if (needsupdate & batchneed)
8389 dynamicvertex = true;
8391 // see if we need to build vertexmesh from arrays
8392 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8393 dynamicvertex = true;
8395 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8396 // also some drivers strongly dislike firstvertex
8397 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8398 dynamicvertex = true;
8400 rsurface.batchvertex3f = rsurface.modelvertex3f;
8401 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8402 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8403 rsurface.batchsvector3f = rsurface.modelsvector3f;
8404 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8405 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8406 rsurface.batchtvector3f = rsurface.modeltvector3f;
8407 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8408 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8409 rsurface.batchnormal3f = rsurface.modelnormal3f;
8410 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8411 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8412 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8413 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8414 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8415 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8416 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8417 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8418 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8419 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8420 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8421 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8422 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8423 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8424 rsurface.batchelement3i = rsurface.modelelement3i;
8425 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8426 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8427 rsurface.batchelement3s = rsurface.modelelement3s;
8428 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8429 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8431 // if any dynamic vertex processing has to occur in software, we copy the
8432 // entire surface list together before processing to rebase the vertices
8433 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8435 // if any gaps exist and we do not have a static vertex buffer, we have to
8436 // copy the surface list together to avoid wasting upload bandwidth on the
8437 // vertices in the gaps.
8439 // if gaps exist and we have a static vertex buffer, we still have to
8440 // combine the index buffer ranges into one dynamic index buffer.
8442 // in all cases we end up with data that can be drawn in one call.
8446 // static vertex data, just set pointers...
8447 rsurface.batchgeneratedvertex = false;
8448 // if there are gaps, we want to build a combined index buffer,
8449 // otherwise use the original static buffer with an appropriate offset
8452 // build a new triangle elements array for this batch
8453 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8454 rsurface.batchfirsttriangle = 0;
8456 for (i = 0;i < texturenumsurfaces;i++)
8458 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8459 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8460 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8461 numtriangles += surfacenumtriangles;
8463 rsurface.batchelement3i_indexbuffer = NULL;
8464 rsurface.batchelement3i_bufferoffset = 0;
8465 rsurface.batchelement3s = NULL;
8466 rsurface.batchelement3s_indexbuffer = NULL;
8467 rsurface.batchelement3s_bufferoffset = 0;
8468 if (endvertex <= 65536)
8470 // make a 16bit (unsigned short) index array if possible
8471 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8472 for (i = 0;i < numtriangles*3;i++)
8473 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8479 // something needs software processing, do it for real...
8480 // we only directly handle separate array data in this case and then
8481 // generate interleaved data if needed...
8482 rsurface.batchgeneratedvertex = true;
8484 // now copy the vertex data into a combined array and make an index array
8485 // (this is what Quake3 does all the time)
8486 //if (gaps || rsurface.batchfirstvertex)
8488 rsurface.batchvertex3fbuffer = NULL;
8489 rsurface.batchvertexmesh = NULL;
8490 rsurface.batchvertexmeshbuffer = NULL;
8491 rsurface.batchvertex3f = NULL;
8492 rsurface.batchvertex3f_vertexbuffer = NULL;
8493 rsurface.batchvertex3f_bufferoffset = 0;
8494 rsurface.batchsvector3f = NULL;
8495 rsurface.batchsvector3f_vertexbuffer = NULL;
8496 rsurface.batchsvector3f_bufferoffset = 0;
8497 rsurface.batchtvector3f = NULL;
8498 rsurface.batchtvector3f_vertexbuffer = NULL;
8499 rsurface.batchtvector3f_bufferoffset = 0;
8500 rsurface.batchnormal3f = NULL;
8501 rsurface.batchnormal3f_vertexbuffer = NULL;
8502 rsurface.batchnormal3f_bufferoffset = 0;
8503 rsurface.batchlightmapcolor4f = NULL;
8504 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8505 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8506 rsurface.batchtexcoordtexture2f = NULL;
8507 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8508 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8509 rsurface.batchtexcoordlightmap2f = NULL;
8510 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8511 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8512 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8513 rsurface.batchelement3i_indexbuffer = NULL;
8514 rsurface.batchelement3i_bufferoffset = 0;
8515 rsurface.batchelement3s = NULL;
8516 rsurface.batchelement3s_indexbuffer = NULL;
8517 rsurface.batchelement3s_bufferoffset = 0;
8518 // we'll only be setting up certain arrays as needed
8519 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8520 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8521 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8522 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8523 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8524 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8525 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8527 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8528 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8530 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8531 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8532 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8533 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8534 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8535 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8538 for (i = 0;i < texturenumsurfaces;i++)
8540 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8541 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8542 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8543 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8544 // copy only the data requested
8545 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8546 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8547 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8549 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8550 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8551 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8552 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8553 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8555 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8556 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8558 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8559 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8560 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8561 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8562 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8563 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8565 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8566 numvertices += surfacenumvertices;
8567 numtriangles += surfacenumtriangles;
8570 // generate a 16bit index array as well if possible
8571 // (in general, dynamic batches fit)
8572 if (numvertices <= 65536)
8574 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8575 for (i = 0;i < numtriangles*3;i++)
8576 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8579 // since we've copied everything, the batch now starts at 0
8580 rsurface.batchfirstvertex = 0;
8581 rsurface.batchnumvertices = batchnumvertices;
8582 rsurface.batchfirsttriangle = 0;
8583 rsurface.batchnumtriangles = batchnumtriangles;
8586 // q1bsp surfaces rendered in vertex color mode have to have colors
8587 // calculated based on lightstyles
8588 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8590 // generate color arrays for the surfaces in this list
8595 const unsigned char *lm;
8596 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8597 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8598 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8600 for (i = 0;i < texturenumsurfaces;i++)
8602 surface = texturesurfacelist[i];
8603 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8604 surfacenumvertices = surface->num_vertices;
8605 if (surface->lightmapinfo->samples)
8607 for (j = 0;j < surfacenumvertices;j++)
8609 lm = surface->lightmapinfo->samples + offsets[j];
8610 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8611 VectorScale(lm, scale, c);
8612 if (surface->lightmapinfo->styles[1] != 255)
8614 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8616 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8617 VectorMA(c, scale, lm, c);
8618 if (surface->lightmapinfo->styles[2] != 255)
8621 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8622 VectorMA(c, scale, lm, c);
8623 if (surface->lightmapinfo->styles[3] != 255)
8626 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8627 VectorMA(c, scale, lm, c);
8634 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);
8640 for (j = 0;j < surfacenumvertices;j++)
8642 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8649 // if vertices are deformed (sprite flares and things in maps, possibly
8650 // water waves, bulges and other deformations), modify the copied vertices
8652 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8654 switch (deform->deform)
8657 case Q3DEFORM_PROJECTIONSHADOW:
8658 case Q3DEFORM_TEXT0:
8659 case Q3DEFORM_TEXT1:
8660 case Q3DEFORM_TEXT2:
8661 case Q3DEFORM_TEXT3:
8662 case Q3DEFORM_TEXT4:
8663 case Q3DEFORM_TEXT5:
8664 case Q3DEFORM_TEXT6:
8665 case Q3DEFORM_TEXT7:
8668 case Q3DEFORM_AUTOSPRITE:
8669 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8670 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8671 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8672 VectorNormalize(newforward);
8673 VectorNormalize(newright);
8674 VectorNormalize(newup);
8675 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8676 // rsurface.batchvertex3f_vertexbuffer = NULL;
8677 // rsurface.batchvertex3f_bufferoffset = 0;
8678 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8679 // rsurface.batchsvector3f_vertexbuffer = NULL;
8680 // rsurface.batchsvector3f_bufferoffset = 0;
8681 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8682 // rsurface.batchtvector3f_vertexbuffer = NULL;
8683 // rsurface.batchtvector3f_bufferoffset = 0;
8684 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8685 // rsurface.batchnormal3f_vertexbuffer = NULL;
8686 // rsurface.batchnormal3f_bufferoffset = 0;
8687 // a single autosprite surface can contain multiple sprites...
8688 for (j = 0;j < batchnumvertices - 3;j += 4)
8690 VectorClear(center);
8691 for (i = 0;i < 4;i++)
8692 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8693 VectorScale(center, 0.25f, center);
8694 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8695 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8696 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8697 for (i = 0;i < 4;i++)
8699 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8700 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8703 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8704 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8705 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);
8707 case Q3DEFORM_AUTOSPRITE2:
8708 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8709 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8710 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8711 VectorNormalize(newforward);
8712 VectorNormalize(newright);
8713 VectorNormalize(newup);
8714 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8715 // rsurface.batchvertex3f_vertexbuffer = NULL;
8716 // rsurface.batchvertex3f_bufferoffset = 0;
8718 const float *v1, *v2;
8728 memset(shortest, 0, sizeof(shortest));
8729 // a single autosprite surface can contain multiple sprites...
8730 for (j = 0;j < batchnumvertices - 3;j += 4)
8732 VectorClear(center);
8733 for (i = 0;i < 4;i++)
8734 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8735 VectorScale(center, 0.25f, center);
8736 // find the two shortest edges, then use them to define the
8737 // axis vectors for rotating around the central axis
8738 for (i = 0;i < 6;i++)
8740 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8741 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8742 l = VectorDistance2(v1, v2);
8743 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8745 l += (1.0f / 1024.0f);
8746 if (shortest[0].length2 > l || i == 0)
8748 shortest[1] = shortest[0];
8749 shortest[0].length2 = l;
8750 shortest[0].v1 = v1;
8751 shortest[0].v2 = v2;
8753 else if (shortest[1].length2 > l || i == 1)
8755 shortest[1].length2 = l;
8756 shortest[1].v1 = v1;
8757 shortest[1].v2 = v2;
8760 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8761 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8762 // this calculates the right vector from the shortest edge
8763 // and the up vector from the edge midpoints
8764 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8765 VectorNormalize(right);
8766 VectorSubtract(end, start, up);
8767 VectorNormalize(up);
8768 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8769 VectorSubtract(rsurface.localvieworigin, center, forward);
8770 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8771 VectorNegate(forward, forward);
8772 VectorReflect(forward, 0, up, forward);
8773 VectorNormalize(forward);
8774 CrossProduct(up, forward, newright);
8775 VectorNormalize(newright);
8776 // rotate the quad around the up axis vector, this is made
8777 // especially easy by the fact we know the quad is flat,
8778 // so we only have to subtract the center position and
8779 // measure distance along the right vector, and then
8780 // multiply that by the newright vector and add back the
8782 // we also need to subtract the old position to undo the
8783 // displacement from the center, which we do with a
8784 // DotProduct, the subtraction/addition of center is also
8785 // optimized into DotProducts here
8786 l = DotProduct(right, center);
8787 for (i = 0;i < 4;i++)
8789 v1 = rsurface.batchvertex3f + 3*(j+i);
8790 f = DotProduct(right, v1) - l;
8791 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8795 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8797 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798 // rsurface.batchnormal3f_vertexbuffer = NULL;
8799 // rsurface.batchnormal3f_bufferoffset = 0;
8800 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8802 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8804 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8805 // rsurface.batchsvector3f_vertexbuffer = NULL;
8806 // rsurface.batchsvector3f_bufferoffset = 0;
8807 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8808 // rsurface.batchtvector3f_vertexbuffer = NULL;
8809 // rsurface.batchtvector3f_bufferoffset = 0;
8810 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);
8813 case Q3DEFORM_NORMAL:
8814 // deform the normals to make reflections wavey
8815 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8816 rsurface.batchnormal3f_vertexbuffer = NULL;
8817 rsurface.batchnormal3f_bufferoffset = 0;
8818 for (j = 0;j < batchnumvertices;j++)
8821 float *normal = rsurface.batchnormal3f + 3*j;
8822 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8823 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8824 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8825 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8826 VectorNormalize(normal);
8828 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8830 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8831 // rsurface.batchsvector3f_vertexbuffer = NULL;
8832 // rsurface.batchsvector3f_bufferoffset = 0;
8833 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8834 // rsurface.batchtvector3f_vertexbuffer = NULL;
8835 // rsurface.batchtvector3f_bufferoffset = 0;
8836 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);
8840 // deform vertex array to make wavey water and flags and such
8841 waveparms[0] = deform->waveparms[0];
8842 waveparms[1] = deform->waveparms[1];
8843 waveparms[2] = deform->waveparms[2];
8844 waveparms[3] = deform->waveparms[3];
8845 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8846 break; // if wavefunc is a nop, don't make a dynamic vertex array
8847 // this is how a divisor of vertex influence on deformation
8848 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8849 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8850 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8851 // rsurface.batchvertex3f_vertexbuffer = NULL;
8852 // rsurface.batchvertex3f_bufferoffset = 0;
8853 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8854 // rsurface.batchnormal3f_vertexbuffer = NULL;
8855 // rsurface.batchnormal3f_bufferoffset = 0;
8856 for (j = 0;j < batchnumvertices;j++)
8858 // if the wavefunc depends on time, evaluate it per-vertex
8861 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8862 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8864 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8866 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8867 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8868 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8870 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871 // rsurface.batchsvector3f_vertexbuffer = NULL;
8872 // rsurface.batchsvector3f_bufferoffset = 0;
8873 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8874 // rsurface.batchtvector3f_vertexbuffer = NULL;
8875 // rsurface.batchtvector3f_bufferoffset = 0;
8876 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);
8879 case Q3DEFORM_BULGE:
8880 // deform vertex array to make the surface have moving bulges
8881 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8882 // rsurface.batchvertex3f_vertexbuffer = NULL;
8883 // rsurface.batchvertex3f_bufferoffset = 0;
8884 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8885 // rsurface.batchnormal3f_vertexbuffer = NULL;
8886 // rsurface.batchnormal3f_bufferoffset = 0;
8887 for (j = 0;j < batchnumvertices;j++)
8889 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8890 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8892 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8893 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8894 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8896 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8897 // rsurface.batchsvector3f_vertexbuffer = NULL;
8898 // rsurface.batchsvector3f_bufferoffset = 0;
8899 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8900 // rsurface.batchtvector3f_vertexbuffer = NULL;
8901 // rsurface.batchtvector3f_bufferoffset = 0;
8902 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);
8906 // deform vertex array
8907 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8908 break; // if wavefunc is a nop, don't make a dynamic vertex array
8909 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8910 VectorScale(deform->parms, scale, waveparms);
8911 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8912 // rsurface.batchvertex3f_vertexbuffer = NULL;
8913 // rsurface.batchvertex3f_bufferoffset = 0;
8914 for (j = 0;j < batchnumvertices;j++)
8915 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8920 // generate texcoords based on the chosen texcoord source
8921 switch(rsurface.texture->tcgen.tcgen)
8924 case Q3TCGEN_TEXTURE:
8926 case Q3TCGEN_LIGHTMAP:
8927 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8928 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8929 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8930 if (rsurface.batchtexcoordlightmap2f)
8931 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8933 case Q3TCGEN_VECTOR:
8934 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8935 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8936 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8937 for (j = 0;j < batchnumvertices;j++)
8939 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8940 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8943 case Q3TCGEN_ENVIRONMENT:
8944 // make environment reflections using a spheremap
8945 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8946 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8947 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8948 for (j = 0;j < batchnumvertices;j++)
8950 // identical to Q3A's method, but executed in worldspace so
8951 // carried models can be shiny too
8953 float viewer[3], d, reflected[3], worldreflected[3];
8955 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8956 // VectorNormalize(viewer);
8958 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8960 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8961 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8962 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8963 // note: this is proportinal to viewer, so we can normalize later
8965 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8966 VectorNormalize(worldreflected);
8968 // note: this sphere map only uses world x and z!
8969 // so positive and negative y will LOOK THE SAME.
8970 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8971 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8975 // the only tcmod that needs software vertex processing is turbulent, so
8976 // check for it here and apply the changes if needed
8977 // and we only support that as the first one
8978 // (handling a mixture of turbulent and other tcmods would be problematic
8979 // without punting it entirely to a software path)
8980 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8982 amplitude = rsurface.texture->tcmods[0].parms[1];
8983 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8984 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8985 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8986 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8987 for (j = 0;j < batchnumvertices;j++)
8989 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);
8990 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8994 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8996 // convert the modified arrays to vertex structs
8997 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8998 // rsurface.batchvertexmeshbuffer = NULL;
8999 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9000 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9001 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9002 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9003 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9004 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9005 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9007 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9009 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9010 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9013 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9014 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9015 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9016 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9017 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9018 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9019 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9020 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9021 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9025 void RSurf_DrawBatch(void)
9027 // sometimes a zero triangle surface (usually a degenerate patch) makes it
9028 // through the pipeline, killing it earlier in the pipeline would have
9029 // per-surface overhead rather than per-batch overhead, so it's best to
9030 // reject it here, before it hits glDraw.
9031 if (rsurface.batchnumtriangles == 0)
9034 // batch debugging code
9035 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9041 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9042 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9045 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9047 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9049 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9050 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);
9057 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);
9060 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9062 // pick the closest matching water plane
9063 int planeindex, vertexindex, bestplaneindex = -1;
9067 r_waterstate_waterplane_t *p;
9068 qboolean prepared = false;
9070 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9072 if(p->camera_entity != rsurface.texture->camera_entity)
9077 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9079 if(rsurface.batchnumvertices == 0)
9082 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9084 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9085 d += fabs(PlaneDiff(vert, &p->plane));
9087 if (bestd > d || bestplaneindex < 0)
9090 bestplaneindex = planeindex;
9093 return bestplaneindex;
9094 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9095 // this situation though, as it might be better to render single larger
9096 // batches with useless stuff (backface culled for example) than to
9097 // render multiple smaller batches
9100 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9103 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9104 rsurface.passcolor4f_vertexbuffer = 0;
9105 rsurface.passcolor4f_bufferoffset = 0;
9106 for (i = 0;i < rsurface.batchnumvertices;i++)
9107 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9110 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9117 if (rsurface.passcolor4f)
9119 // generate color arrays
9120 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9121 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9122 rsurface.passcolor4f_vertexbuffer = 0;
9123 rsurface.passcolor4f_bufferoffset = 0;
9124 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9126 f = RSurf_FogVertex(v);
9135 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9136 rsurface.passcolor4f_vertexbuffer = 0;
9137 rsurface.passcolor4f_bufferoffset = 0;
9138 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9140 f = RSurf_FogVertex(v);
9149 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9156 if (!rsurface.passcolor4f)
9158 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9159 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9160 rsurface.passcolor4f_vertexbuffer = 0;
9161 rsurface.passcolor4f_bufferoffset = 0;
9162 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)
9164 f = RSurf_FogVertex(v);
9165 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9166 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9167 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9172 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9177 if (!rsurface.passcolor4f)
9179 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9180 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9181 rsurface.passcolor4f_vertexbuffer = 0;
9182 rsurface.passcolor4f_bufferoffset = 0;
9183 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9192 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9197 if (!rsurface.passcolor4f)
9199 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9200 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9201 rsurface.passcolor4f_vertexbuffer = 0;
9202 rsurface.passcolor4f_bufferoffset = 0;
9203 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9205 c2[0] = c[0] + r_refdef.scene.ambient;
9206 c2[1] = c[1] + r_refdef.scene.ambient;
9207 c2[2] = c[2] + r_refdef.scene.ambient;
9212 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9215 rsurface.passcolor4f = NULL;
9216 rsurface.passcolor4f_vertexbuffer = 0;
9217 rsurface.passcolor4f_bufferoffset = 0;
9218 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9219 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9220 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9221 GL_Color(r, g, b, a);
9222 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9226 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9228 // TODO: optimize applyfog && applycolor case
9229 // just apply fog if necessary, and tint the fog color array if necessary
9230 rsurface.passcolor4f = NULL;
9231 rsurface.passcolor4f_vertexbuffer = 0;
9232 rsurface.passcolor4f_bufferoffset = 0;
9233 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9234 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9235 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9236 GL_Color(r, g, b, a);
9240 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9243 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9244 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9245 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9246 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9247 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9248 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9249 GL_Color(r, g, b, a);
9253 static void RSurf_DrawBatch_GL11_ClampColor(void)
9258 if (!rsurface.passcolor4f)
9260 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9262 c2[0] = bound(0.0f, c1[0], 1.0f);
9263 c2[1] = bound(0.0f, c1[1], 1.0f);
9264 c2[2] = bound(0.0f, c1[2], 1.0f);
9265 c2[3] = bound(0.0f, c1[3], 1.0f);
9269 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9279 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9280 rsurface.passcolor4f_vertexbuffer = 0;
9281 rsurface.passcolor4f_bufferoffset = 0;
9282 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)
9284 f = -DotProduct(r_refdef.view.forward, n);
9286 f = f * 0.85 + 0.15; // work around so stuff won't get black
9287 f *= r_refdef.lightmapintensity;
9288 Vector4Set(c, f, f, f, 1);
9292 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9294 RSurf_DrawBatch_GL11_ApplyFakeLight();
9295 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9296 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9297 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9298 GL_Color(r, g, b, a);
9302 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9310 vec3_t ambientcolor;
9311 vec3_t diffusecolor;
9315 VectorCopy(rsurface.modellight_lightdir, lightdir);
9316 f = 0.5f * r_refdef.lightmapintensity;
9317 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9318 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9319 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9320 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9321 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9322 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9324 if (VectorLength2(diffusecolor) > 0)
9326 // q3-style directional shading
9327 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328 rsurface.passcolor4f_vertexbuffer = 0;
9329 rsurface.passcolor4f_bufferoffset = 0;
9330 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)
9332 if ((f = DotProduct(n, lightdir)) > 0)
9333 VectorMA(ambientcolor, f, diffusecolor, c);
9335 VectorCopy(ambientcolor, c);
9342 *applycolor = false;
9346 *r = ambientcolor[0];
9347 *g = ambientcolor[1];
9348 *b = ambientcolor[2];
9349 rsurface.passcolor4f = NULL;
9350 rsurface.passcolor4f_vertexbuffer = 0;
9351 rsurface.passcolor4f_bufferoffset = 0;
9355 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9357 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9358 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9359 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9360 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9361 GL_Color(r, g, b, a);
9365 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9373 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9374 rsurface.passcolor4f_vertexbuffer = 0;
9375 rsurface.passcolor4f_bufferoffset = 0;
9377 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9379 f = 1 - RSurf_FogVertex(v);
9387 void RSurf_SetupDepthAndCulling(void)
9389 // submodels are biased to avoid z-fighting with world surfaces that they
9390 // may be exactly overlapping (avoids z-fighting artifacts on certain
9391 // doors and things in Quake maps)
9392 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9393 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9394 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9395 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9398 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9400 // transparent sky would be ridiculous
9401 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9403 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9404 skyrenderlater = true;
9405 RSurf_SetupDepthAndCulling();
9407 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9408 // skymasking on them, and Quake3 never did sky masking (unlike
9409 // software Quake and software Quake2), so disable the sky masking
9410 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9411 // and skymasking also looks very bad when noclipping outside the
9412 // level, so don't use it then either.
9413 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9415 R_Mesh_ResetTextureState();
9416 if (skyrendermasked)
9418 R_SetupShader_DepthOrShadow();
9419 // depth-only (masking)
9420 GL_ColorMask(0,0,0,0);
9421 // just to make sure that braindead drivers don't draw
9422 // anything despite that colormask...
9423 GL_BlendFunc(GL_ZERO, GL_ONE);
9424 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9425 if (rsurface.batchvertex3fbuffer)
9426 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9428 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9432 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9434 GL_BlendFunc(GL_ONE, GL_ZERO);
9435 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9436 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9437 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9440 if (skyrendermasked)
9441 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9443 R_Mesh_ResetTextureState();
9444 GL_Color(1, 1, 1, 1);
9447 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9448 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9449 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9451 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9455 // render screenspace normalmap to texture
9457 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9462 // bind lightmap texture
9464 // water/refraction/reflection/camera surfaces have to be handled specially
9465 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9467 int start, end, startplaneindex;
9468 for (start = 0;start < texturenumsurfaces;start = end)
9470 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9471 if(startplaneindex < 0)
9473 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9474 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9478 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9480 // now that we have a batch using the same planeindex, render it
9481 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9483 // render water or distortion background
9485 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9487 // blend surface on top
9488 GL_DepthMask(false);
9489 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9492 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9494 // render surface with reflection texture as input
9495 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9496 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex));
9503 // render surface batch normally
9504 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9505 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9509 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9511 // OpenGL 1.3 path - anything not completely ancient
9512 qboolean applycolor;
9515 const texturelayer_t *layer;
9516 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9517 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9519 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9522 int layertexrgbscale;
9523 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9525 if (layerindex == 0)
9529 GL_AlphaTest(false);
9530 GL_DepthFunc(GL_EQUAL);
9533 GL_DepthMask(layer->depthmask && writedepth);
9534 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9535 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9537 layertexrgbscale = 4;
9538 VectorScale(layer->color, 0.25f, layercolor);
9540 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9542 layertexrgbscale = 2;
9543 VectorScale(layer->color, 0.5f, layercolor);
9547 layertexrgbscale = 1;
9548 VectorScale(layer->color, 1.0f, layercolor);
9550 layercolor[3] = layer->color[3];
9551 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9552 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9553 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9554 switch (layer->type)
9556 case TEXTURELAYERTYPE_LITTEXTURE:
9557 // single-pass lightmapped texture with 2x rgbscale
9558 R_Mesh_TexBind(0, r_texture_white);
9559 R_Mesh_TexMatrix(0, NULL);
9560 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9561 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9562 R_Mesh_TexBind(1, layer->texture);
9563 R_Mesh_TexMatrix(1, &layer->texmatrix);
9564 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9565 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9566 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9567 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9568 else if (FAKELIGHT_ENABLED)
9569 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9570 else if (rsurface.uselightmaptexture)
9571 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9573 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9575 case TEXTURELAYERTYPE_TEXTURE:
9576 // singletexture unlit texture with transparency support
9577 R_Mesh_TexBind(0, layer->texture);
9578 R_Mesh_TexMatrix(0, &layer->texmatrix);
9579 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9580 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9581 R_Mesh_TexBind(1, 0);
9582 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9583 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9585 case TEXTURELAYERTYPE_FOG:
9586 // singletexture fogging
9589 R_Mesh_TexBind(0, layer->texture);
9590 R_Mesh_TexMatrix(0, &layer->texmatrix);
9591 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9592 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9596 R_Mesh_TexBind(0, 0);
9597 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9599 R_Mesh_TexBind(1, 0);
9600 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9601 // generate a color array for the fog pass
9602 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9603 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9607 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9610 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9612 GL_DepthFunc(GL_LEQUAL);
9613 GL_AlphaTest(false);
9617 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9619 // OpenGL 1.1 - crusty old voodoo path
9622 const texturelayer_t *layer;
9623 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | ((!rsurface.uselightmaptexture && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)) ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.modeltexcoordlightmap2f ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9624 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9626 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9628 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9630 if (layerindex == 0)
9634 GL_AlphaTest(false);
9635 GL_DepthFunc(GL_EQUAL);
9638 GL_DepthMask(layer->depthmask && writedepth);
9639 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9640 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9641 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9642 switch (layer->type)
9644 case TEXTURELAYERTYPE_LITTEXTURE:
9645 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9647 // two-pass lit texture with 2x rgbscale
9648 // first the lightmap pass
9649 R_Mesh_TexBind(0, r_texture_white);
9650 R_Mesh_TexMatrix(0, NULL);
9651 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9652 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9653 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9654 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9655 else if (FAKELIGHT_ENABLED)
9656 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9657 else if (rsurface.uselightmaptexture)
9658 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9660 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9661 // then apply the texture to it
9662 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9663 R_Mesh_TexBind(0, layer->texture);
9664 R_Mesh_TexMatrix(0, &layer->texmatrix);
9665 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9666 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9667 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);
9671 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9672 R_Mesh_TexBind(0, layer->texture);
9673 R_Mesh_TexMatrix(0, &layer->texmatrix);
9674 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9675 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9676 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9677 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);
9679 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);
9682 case TEXTURELAYERTYPE_TEXTURE:
9683 // singletexture unlit texture with transparency support
9684 R_Mesh_TexBind(0, layer->texture);
9685 R_Mesh_TexMatrix(0, &layer->texmatrix);
9686 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9687 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9688 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);
9690 case TEXTURELAYERTYPE_FOG:
9691 // singletexture fogging
9694 R_Mesh_TexBind(0, layer->texture);
9695 R_Mesh_TexMatrix(0, &layer->texmatrix);
9696 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9697 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9701 R_Mesh_TexBind(0, 0);
9702 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9704 // generate a color array for the fog pass
9705 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9706 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9710 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9713 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9715 GL_DepthFunc(GL_LEQUAL);
9716 GL_AlphaTest(false);
9720 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9724 r_vertexgeneric_t *batchvertex;
9727 // R_Mesh_ResetTextureState();
9728 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9730 if(rsurface.texture && rsurface.texture->currentskinframe)
9732 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9733 c[3] *= rsurface.texture->currentalpha;
9743 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9745 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9746 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9747 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9750 // brighten it up (as texture value 127 means "unlit")
9751 c[0] *= 2 * r_refdef.view.colorscale;
9752 c[1] *= 2 * r_refdef.view.colorscale;
9753 c[2] *= 2 * r_refdef.view.colorscale;
9755 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9756 c[3] *= r_wateralpha.value;
9758 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9760 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9761 GL_DepthMask(false);
9763 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9765 GL_BlendFunc(GL_ONE, GL_ONE);
9766 GL_DepthMask(false);
9768 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9770 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9771 GL_DepthMask(false);
9773 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9775 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9776 GL_DepthMask(false);
9780 GL_BlendFunc(GL_ONE, GL_ZERO);
9781 GL_DepthMask(writedepth);
9784 if (r_showsurfaces.integer == 3)
9786 rsurface.passcolor4f = NULL;
9788 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9790 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9792 rsurface.passcolor4f = NULL;
9793 rsurface.passcolor4f_vertexbuffer = 0;
9794 rsurface.passcolor4f_bufferoffset = 0;
9796 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9798 qboolean applycolor = true;
9801 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9803 r_refdef.lightmapintensity = 1;
9804 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9805 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9807 else if (FAKELIGHT_ENABLED)
9809 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9811 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9812 RSurf_DrawBatch_GL11_ApplyFakeLight();
9813 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9817 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9819 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9820 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9821 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9824 if(!rsurface.passcolor4f)
9825 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9827 RSurf_DrawBatch_GL11_ApplyAmbient();
9828 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9829 if(r_refdef.fogenabled)
9830 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9831 RSurf_DrawBatch_GL11_ClampColor();
9833 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9834 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9837 else if (!r_refdef.view.showdebug)
9839 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9840 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9841 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9843 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9844 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9846 R_Mesh_PrepareVertices_Generic_Unlock();
9849 else if (r_showsurfaces.integer == 4)
9851 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9852 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9853 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9855 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9856 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9857 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9859 R_Mesh_PrepareVertices_Generic_Unlock();
9862 else if (r_showsurfaces.integer == 2)
9865 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9866 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9867 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9869 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9870 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9871 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9872 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9873 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9874 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9875 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9877 R_Mesh_PrepareVertices_Generic_Unlock();
9878 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9882 int texturesurfaceindex;
9884 const msurface_t *surface;
9885 float surfacecolor4f[4];
9886 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9887 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9889 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9891 surface = texturesurfacelist[texturesurfaceindex];
9892 k = (int)(((size_t)surface) / sizeof(msurface_t));
9893 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9894 for (j = 0;j < surface->num_vertices;j++)
9896 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9897 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9901 R_Mesh_PrepareVertices_Generic_Unlock();
9906 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9909 RSurf_SetupDepthAndCulling();
9910 if (r_showsurfaces.integer)
9912 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9915 switch (vid.renderpath)
9917 case RENDERPATH_GL20:
9918 case RENDERPATH_D3D9:
9919 case RENDERPATH_D3D10:
9920 case RENDERPATH_D3D11:
9921 case RENDERPATH_SOFT:
9922 case RENDERPATH_GLES2:
9923 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9925 case RENDERPATH_GL13:
9926 case RENDERPATH_GLES1:
9927 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9929 case RENDERPATH_GL11:
9930 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9936 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9939 RSurf_SetupDepthAndCulling();
9940 if (r_showsurfaces.integer)
9942 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9945 switch (vid.renderpath)
9947 case RENDERPATH_GL20:
9948 case RENDERPATH_D3D9:
9949 case RENDERPATH_D3D10:
9950 case RENDERPATH_D3D11:
9951 case RENDERPATH_SOFT:
9952 case RENDERPATH_GLES2:
9953 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9955 case RENDERPATH_GL13:
9956 case RENDERPATH_GLES1:
9957 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9959 case RENDERPATH_GL11:
9960 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9966 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9969 int texturenumsurfaces, endsurface;
9971 const msurface_t *surface;
9972 const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
9974 // if the model is static it doesn't matter what value we give for
9975 // wantnormals and wanttangents, so this logic uses only rules applicable
9976 // to a model, knowing that they are meaningless otherwise
9977 if (ent == r_refdef.scene.worldentity)
9978 RSurf_ActiveWorldEntity();
9979 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9980 RSurf_ActiveModelEntity(ent, false, false, false);
9983 switch (vid.renderpath)
9985 case RENDERPATH_GL20:
9986 case RENDERPATH_D3D9:
9987 case RENDERPATH_D3D10:
9988 case RENDERPATH_D3D11:
9989 case RENDERPATH_SOFT:
9990 case RENDERPATH_GLES2:
9991 RSurf_ActiveModelEntity(ent, true, true, false);
9993 case RENDERPATH_GL11:
9994 case RENDERPATH_GL13:
9995 case RENDERPATH_GLES1:
9996 RSurf_ActiveModelEntity(ent, true, false, false);
10001 if (r_transparentdepthmasking.integer)
10003 qboolean setup = false;
10004 for (i = 0;i < numsurfaces;i = j)
10007 surface = rsurface.modelsurfaces + surfacelist[i];
10008 texture = surface->texture;
10009 rsurface.texture = R_GetCurrentTexture(texture);
10010 rsurface.lightmaptexture = NULL;
10011 rsurface.deluxemaptexture = NULL;
10012 rsurface.uselightmaptexture = false;
10013 // scan ahead until we find a different texture
10014 endsurface = min(i + 1024, numsurfaces);
10015 texturenumsurfaces = 0;
10016 texturesurfacelist[texturenumsurfaces++] = surface;
10017 for (;j < endsurface;j++)
10019 surface = rsurface.modelsurfaces + surfacelist[j];
10020 if (texture != surface->texture)
10022 texturesurfacelist[texturenumsurfaces++] = surface;
10024 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10026 // render the range of surfaces as depth
10030 GL_ColorMask(0,0,0,0);
10032 GL_DepthTest(true);
10033 GL_BlendFunc(GL_ONE, GL_ZERO);
10034 GL_DepthMask(true);
10035 // R_Mesh_ResetTextureState();
10036 R_SetupShader_DepthOrShadow();
10038 RSurf_SetupDepthAndCulling();
10039 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10040 if (rsurface.batchvertex3fbuffer)
10041 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10043 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10047 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10050 for (i = 0;i < numsurfaces;i = j)
10053 surface = rsurface.modelsurfaces + surfacelist[i];
10054 texture = surface->texture;
10055 rsurface.texture = R_GetCurrentTexture(texture);
10056 // scan ahead until we find a different texture
10057 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10058 texturenumsurfaces = 0;
10059 texturesurfacelist[texturenumsurfaces++] = surface;
10060 if(FAKELIGHT_ENABLED)
10062 rsurface.lightmaptexture = NULL;
10063 rsurface.deluxemaptexture = NULL;
10064 rsurface.uselightmaptexture = false;
10065 for (;j < endsurface;j++)
10067 surface = rsurface.modelsurfaces + surfacelist[j];
10068 if (texture != surface->texture)
10070 texturesurfacelist[texturenumsurfaces++] = surface;
10075 rsurface.lightmaptexture = surface->lightmaptexture;
10076 rsurface.deluxemaptexture = surface->deluxemaptexture;
10077 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10078 for (;j < endsurface;j++)
10080 surface = rsurface.modelsurfaces + surfacelist[j];
10081 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10083 texturesurfacelist[texturenumsurfaces++] = surface;
10086 // render the range of surfaces
10087 if (ent == r_refdef.scene.worldentity)
10088 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10090 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10092 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10095 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10097 // transparent surfaces get pushed off into the transparent queue
10098 int surfacelistindex;
10099 const msurface_t *surface;
10100 vec3_t tempcenter, center;
10101 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10103 surface = texturesurfacelist[surfacelistindex];
10104 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10105 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10106 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10107 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10108 if (queueentity->transparent_offset) // transparent offset
10110 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10111 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10112 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10114 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10118 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10120 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10122 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10124 RSurf_SetupDepthAndCulling();
10125 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10126 if (rsurface.batchvertex3fbuffer)
10127 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10129 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10133 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10135 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10138 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10141 if (!rsurface.texture->currentnumlayers)
10143 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10144 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10146 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10148 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10149 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10150 else if (!rsurface.texture->currentnumlayers)
10152 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10154 // in the deferred case, transparent surfaces were queued during prepass
10155 if (!r_shadow_usingdeferredprepass)
10156 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10160 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10161 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10166 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10169 texture_t *texture;
10170 R_FrameData_SetMark();
10171 // break the surface list down into batches by texture and use of lightmapping
10172 for (i = 0;i < numsurfaces;i = j)
10175 // texture is the base texture pointer, rsurface.texture is the
10176 // current frame/skin the texture is directing us to use (for example
10177 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10178 // use skin 1 instead)
10179 texture = surfacelist[i]->texture;
10180 rsurface.texture = R_GetCurrentTexture(texture);
10181 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10183 // if this texture is not the kind we want, skip ahead to the next one
10184 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10188 if(FAKELIGHT_ENABLED || depthonly || prepass)
10190 rsurface.lightmaptexture = NULL;
10191 rsurface.deluxemaptexture = NULL;
10192 rsurface.uselightmaptexture = false;
10193 // simply scan ahead until we find a different texture or lightmap state
10194 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10199 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10200 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10201 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10202 // simply scan ahead until we find a different texture or lightmap state
10203 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10206 // render the range of surfaces
10207 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10209 R_FrameData_ReturnToMark();
10212 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10216 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10219 if (!rsurface.texture->currentnumlayers)
10221 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10222 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10224 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10226 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10227 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10228 else if (!rsurface.texture->currentnumlayers)
10230 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10232 // in the deferred case, transparent surfaces were queued during prepass
10233 if (!r_shadow_usingdeferredprepass)
10234 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10238 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10239 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10244 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10247 texture_t *texture;
10248 R_FrameData_SetMark();
10249 // break the surface list down into batches by texture and use of lightmapping
10250 for (i = 0;i < numsurfaces;i = j)
10253 // texture is the base texture pointer, rsurface.texture is the
10254 // current frame/skin the texture is directing us to use (for example
10255 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10256 // use skin 1 instead)
10257 texture = surfacelist[i]->texture;
10258 rsurface.texture = R_GetCurrentTexture(texture);
10259 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10261 // if this texture is not the kind we want, skip ahead to the next one
10262 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10266 if(FAKELIGHT_ENABLED || depthonly || prepass)
10268 rsurface.lightmaptexture = NULL;
10269 rsurface.deluxemaptexture = NULL;
10270 rsurface.uselightmaptexture = false;
10271 // simply scan ahead until we find a different texture or lightmap state
10272 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10277 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10278 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10279 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10280 // simply scan ahead until we find a different texture or lightmap state
10281 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10284 // render the range of surfaces
10285 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10287 R_FrameData_ReturnToMark();
10290 float locboxvertex3f[6*4*3] =
10292 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10293 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10294 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10295 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10296 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10297 1,0,0, 0,0,0, 0,1,0, 1,1,0
10300 unsigned short locboxelements[6*2*3] =
10305 12,13,14, 12,14,15,
10306 16,17,18, 16,18,19,
10310 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10313 cl_locnode_t *loc = (cl_locnode_t *)ent;
10315 float vertex3f[6*4*3];
10317 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10318 GL_DepthMask(false);
10319 GL_DepthRange(0, 1);
10320 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10321 GL_DepthTest(true);
10322 GL_CullFace(GL_NONE);
10323 R_EntityMatrix(&identitymatrix);
10325 // R_Mesh_ResetTextureState();
10327 i = surfacelist[0];
10328 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10329 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10330 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10331 surfacelist[0] < 0 ? 0.5f : 0.125f);
10333 if (VectorCompare(loc->mins, loc->maxs))
10335 VectorSet(size, 2, 2, 2);
10336 VectorMA(loc->mins, -0.5f, size, mins);
10340 VectorCopy(loc->mins, mins);
10341 VectorSubtract(loc->maxs, loc->mins, size);
10344 for (i = 0;i < 6*4*3;)
10345 for (j = 0;j < 3;j++, i++)
10346 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10348 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10349 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10350 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10353 void R_DrawLocs(void)
10356 cl_locnode_t *loc, *nearestloc;
10358 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10359 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10361 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10362 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10366 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10368 if (decalsystem->decals)
10369 Mem_Free(decalsystem->decals);
10370 memset(decalsystem, 0, sizeof(*decalsystem));
10373 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, int decalsequence)
10376 tridecal_t *decals;
10379 // expand or initialize the system
10380 if (decalsystem->maxdecals <= decalsystem->numdecals)
10382 decalsystem_t old = *decalsystem;
10383 qboolean useshortelements;
10384 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10385 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10386 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)));
10387 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10388 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10389 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10390 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10391 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10392 if (decalsystem->numdecals)
10393 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10395 Mem_Free(old.decals);
10396 for (i = 0;i < decalsystem->maxdecals*3;i++)
10397 decalsystem->element3i[i] = i;
10398 if (useshortelements)
10399 for (i = 0;i < decalsystem->maxdecals*3;i++)
10400 decalsystem->element3s[i] = i;
10403 // grab a decal and search for another free slot for the next one
10404 decals = decalsystem->decals;
10405 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10406 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10408 decalsystem->freedecal = i;
10409 if (decalsystem->numdecals <= i)
10410 decalsystem->numdecals = i + 1;
10412 // initialize the decal
10414 decal->triangleindex = triangleindex;
10415 decal->surfaceindex = surfaceindex;
10416 decal->decalsequence = decalsequence;
10417 decal->color4f[0][0] = c0[0];
10418 decal->color4f[0][1] = c0[1];
10419 decal->color4f[0][2] = c0[2];
10420 decal->color4f[0][3] = 1;
10421 decal->color4f[1][0] = c1[0];
10422 decal->color4f[1][1] = c1[1];
10423 decal->color4f[1][2] = c1[2];
10424 decal->color4f[1][3] = 1;
10425 decal->color4f[2][0] = c2[0];
10426 decal->color4f[2][1] = c2[1];
10427 decal->color4f[2][2] = c2[2];
10428 decal->color4f[2][3] = 1;
10429 decal->vertex3f[0][0] = v0[0];
10430 decal->vertex3f[0][1] = v0[1];
10431 decal->vertex3f[0][2] = v0[2];
10432 decal->vertex3f[1][0] = v1[0];
10433 decal->vertex3f[1][1] = v1[1];
10434 decal->vertex3f[1][2] = v1[2];
10435 decal->vertex3f[2][0] = v2[0];
10436 decal->vertex3f[2][1] = v2[1];
10437 decal->vertex3f[2][2] = v2[2];
10438 decal->texcoord2f[0][0] = t0[0];
10439 decal->texcoord2f[0][1] = t0[1];
10440 decal->texcoord2f[1][0] = t1[0];
10441 decal->texcoord2f[1][1] = t1[1];
10442 decal->texcoord2f[2][0] = t2[0];
10443 decal->texcoord2f[2][1] = t2[1];
10444 TriangleNormal(v0, v1, v2, decal->plane);
10445 VectorNormalize(decal->plane);
10446 decal->plane[3] = DotProduct(v0, decal->plane);
10449 extern cvar_t cl_decals_bias;
10450 extern cvar_t cl_decals_models;
10451 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10452 // baseparms, parms, temps
10453 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
10458 const float *vertex3f;
10459 const float *normal3f;
10461 float points[2][9][3];
10468 e = rsurface.modelelement3i + 3*triangleindex;
10470 vertex3f = rsurface.modelvertex3f;
10471 normal3f = rsurface.modelnormal3f;
10475 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10477 index = 3*e[cornerindex];
10478 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10483 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10485 index = 3*e[cornerindex];
10486 VectorCopy(vertex3f + index, v[cornerindex]);
10491 //TriangleNormal(v[0], v[1], v[2], normal);
10492 //if (DotProduct(normal, localnormal) < 0.0f)
10494 // clip by each of the box planes formed from the projection matrix
10495 // if anything survives, we emit the decal
10496 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]);
10499 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]);
10502 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]);
10505 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]);
10508 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]);
10511 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]);
10514 // some part of the triangle survived, so we have to accept it...
10517 // dynamic always uses the original triangle
10519 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10521 index = 3*e[cornerindex];
10522 VectorCopy(vertex3f + index, v[cornerindex]);
10525 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10527 // convert vertex positions to texcoords
10528 Matrix4x4_Transform(projection, v[cornerindex], temp);
10529 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10530 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10531 // calculate distance fade from the projection origin
10532 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10533 f = bound(0.0f, f, 1.0f);
10534 c[cornerindex][0] = r * f;
10535 c[cornerindex][1] = g * f;
10536 c[cornerindex][2] = b * f;
10537 c[cornerindex][3] = 1.0f;
10538 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10541 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);
10543 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10544 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);
10546 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, int decalsequence)
10548 matrix4x4_t projection;
10549 decalsystem_t *decalsystem;
10552 const msurface_t *surface;
10553 const msurface_t *surfaces;
10554 const int *surfacelist;
10555 const texture_t *texture;
10557 int numsurfacelist;
10558 int surfacelistindex;
10561 float localorigin[3];
10562 float localnormal[3];
10563 float localmins[3];
10564 float localmaxs[3];
10567 float planes[6][4];
10570 int bih_triangles_count;
10571 int bih_triangles[256];
10572 int bih_surfaces[256];
10574 decalsystem = &ent->decalsystem;
10575 model = ent->model;
10576 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10578 R_DecalSystem_Reset(&ent->decalsystem);
10582 if (!model->brush.data_leafs && !cl_decals_models.integer)
10584 if (decalsystem->model)
10585 R_DecalSystem_Reset(decalsystem);
10589 if (decalsystem->model != model)
10590 R_DecalSystem_Reset(decalsystem);
10591 decalsystem->model = model;
10593 RSurf_ActiveModelEntity(ent, true, false, false);
10595 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10596 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10597 VectorNormalize(localnormal);
10598 localsize = worldsize*rsurface.inversematrixscale;
10599 localmins[0] = localorigin[0] - localsize;
10600 localmins[1] = localorigin[1] - localsize;
10601 localmins[2] = localorigin[2] - localsize;
10602 localmaxs[0] = localorigin[0] + localsize;
10603 localmaxs[1] = localorigin[1] + localsize;
10604 localmaxs[2] = localorigin[2] + localsize;
10606 //VectorCopy(localnormal, planes[4]);
10607 //VectorVectors(planes[4], planes[2], planes[0]);
10608 AnglesFromVectors(angles, localnormal, NULL, false);
10609 AngleVectors(angles, planes[0], planes[2], planes[4]);
10610 VectorNegate(planes[0], planes[1]);
10611 VectorNegate(planes[2], planes[3]);
10612 VectorNegate(planes[4], planes[5]);
10613 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10614 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10615 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10616 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10617 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10618 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10623 matrix4x4_t forwardprojection;
10624 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10625 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10630 float projectionvector[4][3];
10631 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10632 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10633 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10634 projectionvector[0][0] = planes[0][0] * ilocalsize;
10635 projectionvector[0][1] = planes[1][0] * ilocalsize;
10636 projectionvector[0][2] = planes[2][0] * ilocalsize;
10637 projectionvector[1][0] = planes[0][1] * ilocalsize;
10638 projectionvector[1][1] = planes[1][1] * ilocalsize;
10639 projectionvector[1][2] = planes[2][1] * ilocalsize;
10640 projectionvector[2][0] = planes[0][2] * ilocalsize;
10641 projectionvector[2][1] = planes[1][2] * ilocalsize;
10642 projectionvector[2][2] = planes[2][2] * ilocalsize;
10643 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10644 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10645 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10646 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10650 dynamic = model->surfmesh.isanimated;
10651 numsurfacelist = model->nummodelsurfaces;
10652 surfacelist = model->sortedmodelsurfaces;
10653 surfaces = model->data_surfaces;
10656 bih_triangles_count = -1;
10659 if(model->render_bih.numleafs)
10660 bih = &model->render_bih;
10661 else if(model->collision_bih.numleafs)
10662 bih = &model->collision_bih;
10665 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10666 if(bih_triangles_count == 0)
10668 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10670 if(bih_triangles_count > 0)
10672 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10674 surfaceindex = bih_surfaces[triangleindex];
10675 surface = surfaces + surfaceindex;
10676 texture = surface->texture;
10677 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10679 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10681 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10686 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10688 surfaceindex = surfacelist[surfacelistindex];
10689 surface = surfaces + surfaceindex;
10690 // check cull box first because it rejects more than any other check
10691 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10693 // skip transparent surfaces
10694 texture = surface->texture;
10695 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10697 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10699 numtriangles = surface->num_triangles;
10700 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10701 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10706 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10707 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, int decalsequence)
10709 int renderentityindex;
10710 float worldmins[3];
10711 float worldmaxs[3];
10712 entity_render_t *ent;
10714 if (!cl_decals_newsystem.integer)
10717 worldmins[0] = worldorigin[0] - worldsize;
10718 worldmins[1] = worldorigin[1] - worldsize;
10719 worldmins[2] = worldorigin[2] - worldsize;
10720 worldmaxs[0] = worldorigin[0] + worldsize;
10721 worldmaxs[1] = worldorigin[1] + worldsize;
10722 worldmaxs[2] = worldorigin[2] + worldsize;
10724 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10726 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10728 ent = r_refdef.scene.entities[renderentityindex];
10729 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10732 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10736 typedef struct r_decalsystem_splatqueue_s
10738 vec3_t worldorigin;
10739 vec3_t worldnormal;
10745 r_decalsystem_splatqueue_t;
10747 int r_decalsystem_numqueued = 0;
10748 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10750 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)
10752 r_decalsystem_splatqueue_t *queue;
10754 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10757 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10758 VectorCopy(worldorigin, queue->worldorigin);
10759 VectorCopy(worldnormal, queue->worldnormal);
10760 Vector4Set(queue->color, r, g, b, a);
10761 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10762 queue->worldsize = worldsize;
10763 queue->decalsequence = cl.decalsequence++;
10766 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10769 r_decalsystem_splatqueue_t *queue;
10771 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10772 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);
10773 r_decalsystem_numqueued = 0;
10776 extern cvar_t cl_decals_max;
10777 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10780 decalsystem_t *decalsystem = &ent->decalsystem;
10787 if (!decalsystem->numdecals)
10790 if (r_showsurfaces.integer)
10793 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10795 R_DecalSystem_Reset(decalsystem);
10799 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10800 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10802 if (decalsystem->lastupdatetime)
10803 frametime = (cl.time - decalsystem->lastupdatetime);
10806 decalsystem->lastupdatetime = cl.time;
10807 decal = decalsystem->decals;
10808 numdecals = decalsystem->numdecals;
10810 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10812 if (decal->color4f[0][3])
10814 decal->lived += frametime;
10815 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10817 memset(decal, 0, sizeof(*decal));
10818 if (decalsystem->freedecal > i)
10819 decalsystem->freedecal = i;
10823 decal = decalsystem->decals;
10824 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10827 // collapse the array by shuffling the tail decals into the gaps
10830 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10831 decalsystem->freedecal++;
10832 if (decalsystem->freedecal == numdecals)
10834 decal[decalsystem->freedecal] = decal[--numdecals];
10837 decalsystem->numdecals = numdecals;
10839 if (numdecals <= 0)
10841 // if there are no decals left, reset decalsystem
10842 R_DecalSystem_Reset(decalsystem);
10846 extern skinframe_t *decalskinframe;
10847 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10850 decalsystem_t *decalsystem = &ent->decalsystem;
10859 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10862 numdecals = decalsystem->numdecals;
10866 if (r_showsurfaces.integer)
10869 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10871 R_DecalSystem_Reset(decalsystem);
10875 // if the model is static it doesn't matter what value we give for
10876 // wantnormals and wanttangents, so this logic uses only rules applicable
10877 // to a model, knowing that they are meaningless otherwise
10878 if (ent == r_refdef.scene.worldentity)
10879 RSurf_ActiveWorldEntity();
10881 RSurf_ActiveModelEntity(ent, false, false, false);
10883 decalsystem->lastupdatetime = cl.time;
10884 decal = decalsystem->decals;
10886 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10888 // update vertex positions for animated models
10889 v3f = decalsystem->vertex3f;
10890 c4f = decalsystem->color4f;
10891 t2f = decalsystem->texcoord2f;
10892 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10894 if (!decal->color4f[0][3])
10897 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10901 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10904 // update color values for fading decals
10905 if (decal->lived >= cl_decals_time.value)
10906 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10910 c4f[ 0] = decal->color4f[0][0] * alpha;
10911 c4f[ 1] = decal->color4f[0][1] * alpha;
10912 c4f[ 2] = decal->color4f[0][2] * alpha;
10914 c4f[ 4] = decal->color4f[1][0] * alpha;
10915 c4f[ 5] = decal->color4f[1][1] * alpha;
10916 c4f[ 6] = decal->color4f[1][2] * alpha;
10918 c4f[ 8] = decal->color4f[2][0] * alpha;
10919 c4f[ 9] = decal->color4f[2][1] * alpha;
10920 c4f[10] = decal->color4f[2][2] * alpha;
10923 t2f[0] = decal->texcoord2f[0][0];
10924 t2f[1] = decal->texcoord2f[0][1];
10925 t2f[2] = decal->texcoord2f[1][0];
10926 t2f[3] = decal->texcoord2f[1][1];
10927 t2f[4] = decal->texcoord2f[2][0];
10928 t2f[5] = decal->texcoord2f[2][1];
10930 // update vertex positions for animated models
10931 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10933 e = rsurface.modelelement3i + 3*decal->triangleindex;
10934 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10935 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10936 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10940 VectorCopy(decal->vertex3f[0], v3f);
10941 VectorCopy(decal->vertex3f[1], v3f + 3);
10942 VectorCopy(decal->vertex3f[2], v3f + 6);
10945 if (r_refdef.fogenabled)
10947 alpha = RSurf_FogVertex(v3f);
10948 VectorScale(c4f, alpha, c4f);
10949 alpha = RSurf_FogVertex(v3f + 3);
10950 VectorScale(c4f + 4, alpha, c4f + 4);
10951 alpha = RSurf_FogVertex(v3f + 6);
10952 VectorScale(c4f + 8, alpha, c4f + 8);
10963 r_refdef.stats.drawndecals += numtris;
10965 // now render the decals all at once
10966 // (this assumes they all use one particle font texture!)
10967 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, rsurface.ent_shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
10968 // R_Mesh_ResetTextureState();
10969 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10970 GL_DepthMask(false);
10971 GL_DepthRange(0, 1);
10972 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10973 GL_DepthTest(true);
10974 GL_CullFace(GL_NONE);
10975 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10976 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10977 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10981 static void R_DrawModelDecals(void)
10985 // fade faster when there are too many decals
10986 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10987 for (i = 0;i < r_refdef.scene.numentities;i++)
10988 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10990 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10991 for (i = 0;i < r_refdef.scene.numentities;i++)
10992 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10993 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10995 R_DecalSystem_ApplySplatEntitiesQueue();
10997 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10998 for (i = 0;i < r_refdef.scene.numentities;i++)
10999 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11001 r_refdef.stats.totaldecals += numdecals;
11003 if (r_showsurfaces.integer)
11006 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11008 for (i = 0;i < r_refdef.scene.numentities;i++)
11010 if (!r_refdef.viewcache.entityvisible[i])
11012 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11013 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11017 extern cvar_t mod_collision_bih;
11018 void R_DrawDebugModel(void)
11020 entity_render_t *ent = rsurface.entity;
11021 int i, j, k, l, flagsmask;
11022 const msurface_t *surface;
11023 dp_model_t *model = ent->model;
11026 if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11029 if (r_showoverdraw.value > 0)
11031 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11032 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11033 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11034 GL_DepthTest(false);
11035 GL_DepthMask(false);
11036 GL_DepthRange(0, 1);
11037 GL_BlendFunc(GL_ONE, GL_ONE);
11038 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11040 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11042 rsurface.texture = R_GetCurrentTexture(surface->texture);
11043 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11045 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11046 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11047 if (!rsurface.texture->currentlayers->depthmask)
11048 GL_Color(c, 0, 0, 1.0f);
11049 else if (ent == r_refdef.scene.worldentity)
11050 GL_Color(c, c, c, 1.0f);
11052 GL_Color(0, c, 0, 1.0f);
11053 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11057 rsurface.texture = NULL;
11060 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11062 // R_Mesh_ResetTextureState();
11063 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11064 GL_DepthRange(0, 1);
11065 GL_DepthTest(!r_showdisabledepthtest.integer);
11066 GL_DepthMask(false);
11067 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11069 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11073 qboolean cullbox = ent == r_refdef.scene.worldentity;
11074 const q3mbrush_t *brush;
11075 const bih_t *bih = &model->collision_bih;
11076 const bih_leaf_t *bihleaf;
11077 float vertex3f[3][3];
11078 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11080 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11082 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11084 switch (bihleaf->type)
11087 brush = model->brush.data_brushes + bihleaf->itemindex;
11088 if (brush->colbrushf && brush->colbrushf->numtriangles)
11090 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);
11091 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11092 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11095 case BIH_COLLISIONTRIANGLE:
11096 triangleindex = bihleaf->itemindex;
11097 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11098 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11099 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11100 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);
11101 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11102 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11104 case BIH_RENDERTRIANGLE:
11105 triangleindex = bihleaf->itemindex;
11106 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11107 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11108 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11109 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);
11110 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11111 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11117 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11119 if (r_showtris.integer && qglPolygonMode)
11121 if (r_showdisabledepthtest.integer)
11123 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11124 GL_DepthMask(false);
11128 GL_BlendFunc(GL_ONE, GL_ZERO);
11129 GL_DepthMask(true);
11131 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11132 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11134 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11136 rsurface.texture = R_GetCurrentTexture(surface->texture);
11137 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11139 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11140 if (!rsurface.texture->currentlayers->depthmask)
11141 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11142 else if (ent == r_refdef.scene.worldentity)
11143 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11145 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11146 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11150 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11151 rsurface.texture = NULL;
11154 if (r_shownormals.value != 0 && qglBegin)
11156 if (r_showdisabledepthtest.integer)
11158 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11159 GL_DepthMask(false);
11163 GL_BlendFunc(GL_ONE, GL_ZERO);
11164 GL_DepthMask(true);
11166 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11168 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11170 rsurface.texture = R_GetCurrentTexture(surface->texture);
11171 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11173 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11174 qglBegin(GL_LINES);
11175 if (r_shownormals.value < 0)
11177 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11179 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11180 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11181 qglVertex3f(v[0], v[1], v[2]);
11182 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11183 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11184 qglVertex3f(v[0], v[1], v[2]);
11187 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11189 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11191 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11192 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11193 qglVertex3f(v[0], v[1], v[2]);
11194 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11195 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11196 qglVertex3f(v[0], v[1], v[2]);
11198 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11200 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11201 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11202 qglVertex3f(v[0], v[1], v[2]);
11203 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11204 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11205 qglVertex3f(v[0], v[1], v[2]);
11207 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11209 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11210 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11211 qglVertex3f(v[0], v[1], v[2]);
11212 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11213 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11214 qglVertex3f(v[0], v[1], v[2]);
11221 rsurface.texture = NULL;
11225 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11226 int r_maxsurfacelist = 0;
11227 const msurface_t **r_surfacelist = NULL;
11228 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11230 int i, j, endj, flagsmask;
11231 dp_model_t *model = r_refdef.scene.worldmodel;
11232 msurface_t *surfaces;
11233 unsigned char *update;
11234 int numsurfacelist = 0;
11238 if (r_maxsurfacelist < model->num_surfaces)
11240 r_maxsurfacelist = model->num_surfaces;
11242 Mem_Free((msurface_t**)r_surfacelist);
11243 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11246 RSurf_ActiveWorldEntity();
11248 surfaces = model->data_surfaces;
11249 update = model->brushq1.lightmapupdateflags;
11251 // update light styles on this submodel
11252 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11254 model_brush_lightstyleinfo_t *style;
11255 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11257 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11259 int *list = style->surfacelist;
11260 style->value = r_refdef.scene.lightstylevalue[style->style];
11261 for (j = 0;j < style->numsurfaces;j++)
11262 update[list[j]] = true;
11267 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11271 R_DrawDebugModel();
11272 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11276 rsurface.lightmaptexture = NULL;
11277 rsurface.deluxemaptexture = NULL;
11278 rsurface.uselightmaptexture = false;
11279 rsurface.texture = NULL;
11280 rsurface.rtlight = NULL;
11281 numsurfacelist = 0;
11282 // add visible surfaces to draw list
11283 for (i = 0;i < model->nummodelsurfaces;i++)
11285 j = model->sortedmodelsurfaces[i];
11286 if (r_refdef.viewcache.world_surfacevisible[j])
11287 r_surfacelist[numsurfacelist++] = surfaces + j;
11289 // update lightmaps if needed
11290 if (model->brushq1.firstrender)
11292 model->brushq1.firstrender = false;
11293 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11295 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11299 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11300 if (r_refdef.viewcache.world_surfacevisible[j])
11302 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11304 // don't do anything if there were no surfaces
11305 if (!numsurfacelist)
11307 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11310 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11312 // add to stats if desired
11313 if (r_speeds.integer && !skysurfaces && !depthonly)
11315 r_refdef.stats.world_surfaces += numsurfacelist;
11316 for (j = 0;j < numsurfacelist;j++)
11317 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11320 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11323 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11325 int i, j, endj, flagsmask;
11326 dp_model_t *model = ent->model;
11327 msurface_t *surfaces;
11328 unsigned char *update;
11329 int numsurfacelist = 0;
11333 if (r_maxsurfacelist < model->num_surfaces)
11335 r_maxsurfacelist = model->num_surfaces;
11337 Mem_Free((msurface_t **)r_surfacelist);
11338 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11341 // if the model is static it doesn't matter what value we give for
11342 // wantnormals and wanttangents, so this logic uses only rules applicable
11343 // to a model, knowing that they are meaningless otherwise
11344 if (ent == r_refdef.scene.worldentity)
11345 RSurf_ActiveWorldEntity();
11346 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11347 RSurf_ActiveModelEntity(ent, false, false, false);
11349 RSurf_ActiveModelEntity(ent, true, true, true);
11350 else if (depthonly)
11352 switch (vid.renderpath)
11354 case RENDERPATH_GL20:
11355 case RENDERPATH_D3D9:
11356 case RENDERPATH_D3D10:
11357 case RENDERPATH_D3D11:
11358 case RENDERPATH_SOFT:
11359 case RENDERPATH_GLES2:
11360 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11362 case RENDERPATH_GL11:
11363 case RENDERPATH_GL13:
11364 case RENDERPATH_GLES1:
11365 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11371 switch (vid.renderpath)
11373 case RENDERPATH_GL20:
11374 case RENDERPATH_D3D9:
11375 case RENDERPATH_D3D10:
11376 case RENDERPATH_D3D11:
11377 case RENDERPATH_SOFT:
11378 case RENDERPATH_GLES2:
11379 RSurf_ActiveModelEntity(ent, true, true, false);
11381 case RENDERPATH_GL11:
11382 case RENDERPATH_GL13:
11383 case RENDERPATH_GLES1:
11384 RSurf_ActiveModelEntity(ent, true, false, false);
11389 surfaces = model->data_surfaces;
11390 update = model->brushq1.lightmapupdateflags;
11392 // update light styles
11393 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11395 model_brush_lightstyleinfo_t *style;
11396 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11398 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11400 int *list = style->surfacelist;
11401 style->value = r_refdef.scene.lightstylevalue[style->style];
11402 for (j = 0;j < style->numsurfaces;j++)
11403 update[list[j]] = true;
11408 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11412 R_DrawDebugModel();
11413 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11417 rsurface.lightmaptexture = NULL;
11418 rsurface.deluxemaptexture = NULL;
11419 rsurface.uselightmaptexture = false;
11420 rsurface.texture = NULL;
11421 rsurface.rtlight = NULL;
11422 numsurfacelist = 0;
11423 // add visible surfaces to draw list
11424 for (i = 0;i < model->nummodelsurfaces;i++)
11425 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11426 // don't do anything if there were no surfaces
11427 if (!numsurfacelist)
11429 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11432 // update lightmaps if needed
11436 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11441 R_BuildLightMap(ent, surfaces + j);
11446 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11448 R_BuildLightMap(ent, surfaces + j);
11449 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11451 // add to stats if desired
11452 if (r_speeds.integer && !skysurfaces && !depthonly)
11454 r_refdef.stats.entities_surfaces += numsurfacelist;
11455 for (j = 0;j < numsurfacelist;j++)
11456 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11459 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11462 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11464 static texture_t texture;
11465 static msurface_t surface;
11466 const msurface_t *surfacelist = &surface;
11468 // fake enough texture and surface state to render this geometry
11470 texture.update_lastrenderframe = -1; // regenerate this texture
11471 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11472 texture.currentskinframe = skinframe;
11473 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11474 texture.offsetmapping = OFFSETMAPPING_OFF;
11475 texture.offsetscale = 1;
11476 texture.specularscalemod = 1;
11477 texture.specularpowermod = 1;
11479 surface.texture = &texture;
11480 surface.num_triangles = numtriangles;
11481 surface.num_firsttriangle = firsttriangle;
11482 surface.num_vertices = numvertices;
11483 surface.num_firstvertex = firstvertex;
11486 rsurface.texture = R_GetCurrentTexture(surface.texture);
11487 rsurface.lightmaptexture = NULL;
11488 rsurface.deluxemaptexture = NULL;
11489 rsurface.uselightmaptexture = false;
11490 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11493 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)
11495 static msurface_t surface;
11496 const msurface_t *surfacelist = &surface;
11498 // fake enough texture and surface state to render this geometry
11499 surface.texture = texture;
11500 surface.num_triangles = numtriangles;
11501 surface.num_firsttriangle = firsttriangle;
11502 surface.num_vertices = numvertices;
11503 surface.num_firstvertex = firstvertex;
11506 rsurface.texture = R_GetCurrentTexture(surface.texture);
11507 rsurface.lightmaptexture = NULL;
11508 rsurface.deluxemaptexture = NULL;
11509 rsurface.uselightmaptexture = false;
11510 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);