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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
74 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
75 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)"};
76 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
77 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
78 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"};
79 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"};
80 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
81 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"};
82 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"};
83 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"};
84 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
85 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
86 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
87 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
88 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
89 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
90 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
91 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)"};
92 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)"};
93 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
94 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
95 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
96 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
98 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
99 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
100 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
102 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
103 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
104 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
105 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."};
106 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
107 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
108 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
109 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."};
110 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
111 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
112 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
113 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
114 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"};
115 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"};
116 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
118 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
119 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
120 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
121 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"};
123 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
124 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
125 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
126 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
127 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
128 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
129 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
130 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
132 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)"};
133 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"};
135 cvar_t r_texture_sRGB_2d = {0, "r_texture_sRGB_2d", "0", "load textures as sRGB"};
136 cvar_t r_texture_sRGB_skin_diffuse = {0, "r_texture_sRGB_skin_diffuse", "0", "load textures as sRGB"};
137 cvar_t r_texture_sRGB_skin_gloss = {0, "r_texture_sRGB_skin_gloss", "0", "load textures as sRGB"};
138 cvar_t r_texture_sRGB_skin_glow = {0, "r_texture_sRGB_skin_glow", "0", "load textures as sRGB"};
139 cvar_t r_texture_sRGB_skin_reflect = {0, "r_texture_sRGB_skin_reflect", "0", "load textures as sRGB"};
140 cvar_t r_texture_sRGB_cubemap = {0, "r_texture_sRGB_cubemap", "0", "load textures as sRGB"};
141 cvar_t r_texture_sRGB_skybox = {0, "r_texture_sRGB_skybox", "0", "load textures as sRGB"};
143 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
144 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
145 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
147 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"};
148 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"};
149 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
150 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
151 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"};
152 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)"};
153 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)"};
154 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
156 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)"};
157 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
158 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)"};
159 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
160 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)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
163 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
173 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)"};
174 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
175 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"};
176 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
177 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
178 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
181 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
182 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
183 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
185 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
186 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
187 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
188 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
189 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
190 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
191 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
193 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
194 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
195 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
196 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)"};
197 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
198 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
199 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
200 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
201 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
202 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
204 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"};
206 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"};
208 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
210 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
211 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"};
212 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
213 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
214 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
215 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
216 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)"};
217 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
218 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 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"};
223 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."};
225 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)"};
227 extern cvar_t v_glslgamma;
229 extern qboolean v_flipped_state;
231 static struct r_bloomstate_s
236 int bloomwidth, bloomheight;
238 textype_t texturetype;
239 int viewfbo; // used to check if r_viewfbo cvar has changed
241 int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242 rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243 rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
245 int screentexturewidth, screentextureheight;
246 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
248 int bloomtexturewidth, bloomtextureheight;
249 rtexture_t *texture_bloom;
251 // arrays for rendering the screen passes
252 float screentexcoord2f[8];
253 float bloomtexcoord2f[8];
254 float offsettexcoord2f[8];
256 r_viewport_t viewport;
260 r_waterstate_t r_waterstate;
262 /// shadow volume bsp struct with automatically growing nodes buffer
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
287 int r_texture_numcubemaps;
288 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
294 typedef struct r_qwskincache_s
296 char name[MAX_QPATH];
297 skinframe_t *skinframe;
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
314 const float r_d3dscreenvertex3f[12] =
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
325 for (i = 0;i < verts;i++)
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
339 for (i = 0;i < verts;i++)
349 // FIXME: move this to client?
352 if (gamemode == GAME_NEHAHRA)
354 Cvar_Set("gl_fogenable", "0");
355 Cvar_Set("gl_fogdensity", "0.2");
356 Cvar_Set("gl_fogred", "0.3");
357 Cvar_Set("gl_foggreen", "0.3");
358 Cvar_Set("gl_fogblue", "0.3");
360 r_refdef.fog_density = 0;
361 r_refdef.fog_red = 0;
362 r_refdef.fog_green = 0;
363 r_refdef.fog_blue = 0;
364 r_refdef.fog_alpha = 1;
365 r_refdef.fog_start = 0;
366 r_refdef.fog_end = 16384;
367 r_refdef.fog_height = 1<<30;
368 r_refdef.fog_fadedepth = 128;
369 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
372 static void R_BuildBlankTextures(void)
374 unsigned char data[4];
375 data[2] = 128; // normal X
376 data[1] = 128; // normal Y
377 data[0] = 255; // normal Z
378 data[3] = 128; // height
379 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 static void R_BuildNoTexture(void)
400 unsigned char pix[16][16][4];
401 // this makes a light grey/dark grey checkerboard texture
402 for (y = 0;y < 16;y++)
404 for (x = 0;x < 16;x++)
406 if ((y < 8) ^ (x < 8))
422 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
425 static void R_BuildWhiteCube(void)
427 unsigned char data[6*1*1*4];
428 memset(data, 255, sizeof(data));
429 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
432 static void R_BuildNormalizationCube(void)
436 vec_t s, t, intensity;
439 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440 for (side = 0;side < 6;side++)
442 for (y = 0;y < NORMSIZE;y++)
444 for (x = 0;x < NORMSIZE;x++)
446 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
482 intensity = 127.0f / sqrt(DotProduct(v, v));
483 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486 data[((side*64+y)*64+x)*4+3] = 255;
490 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
494 static void R_BuildFogTexture(void)
498 unsigned char data1[FOGWIDTH][4];
499 //unsigned char data2[FOGWIDTH][4];
502 r_refdef.fogmasktable_start = r_refdef.fog_start;
503 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504 r_refdef.fogmasktable_range = r_refdef.fogrange;
505 r_refdef.fogmasktable_density = r_refdef.fog_density;
507 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
510 d = (x * r - r_refdef.fogmasktable_start);
511 if(developer_extra.integer)
512 Con_DPrintf("%f ", d);
514 if (r_fog_exp2.integer)
515 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
517 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518 if(developer_extra.integer)
519 Con_DPrintf(" : %f ", alpha);
520 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521 if(developer_extra.integer)
522 Con_DPrintf(" = %f\n", alpha);
523 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
526 for (x = 0;x < FOGWIDTH;x++)
528 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
533 //data2[x][0] = 255 - b;
534 //data2[x][1] = 255 - b;
535 //data2[x][2] = 255 - b;
538 if (r_texture_fogattenuation)
540 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
545 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
550 static void R_BuildFogHeightTexture(void)
552 unsigned char *inpixels;
560 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561 if (r_refdef.fogheighttexturename[0])
562 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
565 r_refdef.fog_height_tablesize = 0;
566 if (r_texture_fogheighttexture)
567 R_FreeTexture(r_texture_fogheighttexture);
568 r_texture_fogheighttexture = NULL;
569 if (r_refdef.fog_height_table2d)
570 Mem_Free(r_refdef.fog_height_table2d);
571 r_refdef.fog_height_table2d = NULL;
572 if (r_refdef.fog_height_table1d)
573 Mem_Free(r_refdef.fog_height_table1d);
574 r_refdef.fog_height_table1d = NULL;
578 r_refdef.fog_height_tablesize = size;
579 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
583 // LordHavoc: now the magic - what is that table2d for? it is a cooked
584 // average fog color table accounting for every fog layer between a point
585 // and the camera. (Note: attenuation is handled separately!)
586 for (y = 0;y < size;y++)
588 for (x = 0;x < size;x++)
594 for (j = x;j <= y;j++)
596 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602 for (j = x;j >= y;j--)
604 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
609 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
615 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
618 //=======================================================================================================================================================
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
631 //=======================================================================================================================================================
633 typedef struct shaderpermutationinfo_s
638 shaderpermutationinfo_t;
640 typedef struct shadermodeinfo_s
642 const char *vertexfilename;
643 const char *geometryfilename;
644 const char *fragmentfilename;
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
653 {"#define USEDIFFUSE\n", " diffuse"},
654 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655 {"#define USEVIEWTINT\n", " viewtint"},
656 {"#define USECOLORMAPPING\n", " colormapping"},
657 {"#define USESATURATION\n", " saturation"},
658 {"#define USEFOGINSIDE\n", " foginside"},
659 {"#define USEFOGOUTSIDE\n", " fogoutside"},
660 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662 {"#define USEGAMMARAMPS\n", " gammaramps"},
663 {"#define USECUBEFILTER\n", " cubefilter"},
664 {"#define USEGLOW\n", " glow"},
665 {"#define USEBLOOM\n", " bloom"},
666 {"#define USESPECULAR\n", " specular"},
667 {"#define USEPOSTPROCESSING\n", " postprocessing"},
668 {"#define USEREFLECTION\n", " reflection"},
669 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678 {"#define USEALPHAKILL\n", " alphakill"},
679 {"#define USEREFLECTCUBE\n", " reflectcube"},
680 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681 {"#define USEBOUNCEGRID\n", " bouncegrid"},
682 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
701 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
718 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
719 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
720 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
721 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
722 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
723 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 struct r_glsl_permutation_s;
727 typedef struct r_glsl_permutation_s
730 struct r_glsl_permutation_s *hashnext;
732 unsigned int permutation;
734 /// indicates if we have tried compiling this permutation already
736 /// 0 if compilation failed
738 // texture units assigned to each detected uniform
739 int tex_Texture_First;
740 int tex_Texture_Second;
741 int tex_Texture_GammaRamps;
742 int tex_Texture_Normal;
743 int tex_Texture_Color;
744 int tex_Texture_Gloss;
745 int tex_Texture_Glow;
746 int tex_Texture_SecondaryNormal;
747 int tex_Texture_SecondaryColor;
748 int tex_Texture_SecondaryGloss;
749 int tex_Texture_SecondaryGlow;
750 int tex_Texture_Pants;
751 int tex_Texture_Shirt;
752 int tex_Texture_FogHeightTexture;
753 int tex_Texture_FogMask;
754 int tex_Texture_Lightmap;
755 int tex_Texture_Deluxemap;
756 int tex_Texture_Attenuation;
757 int tex_Texture_Cube;
758 int tex_Texture_Refraction;
759 int tex_Texture_Reflection;
760 int tex_Texture_ShadowMap2D;
761 int tex_Texture_CubeProjection;
762 int tex_Texture_ScreenDepth;
763 int tex_Texture_ScreenNormalMap;
764 int tex_Texture_ScreenDiffuse;
765 int tex_Texture_ScreenSpecular;
766 int tex_Texture_ReflectMask;
767 int tex_Texture_ReflectCube;
768 int tex_Texture_BounceGrid;
769 /// locations of detected uniforms in program object, or -1 if not found
770 int loc_Texture_First;
771 int loc_Texture_Second;
772 int loc_Texture_GammaRamps;
773 int loc_Texture_Normal;
774 int loc_Texture_Color;
775 int loc_Texture_Gloss;
776 int loc_Texture_Glow;
777 int loc_Texture_SecondaryNormal;
778 int loc_Texture_SecondaryColor;
779 int loc_Texture_SecondaryGloss;
780 int loc_Texture_SecondaryGlow;
781 int loc_Texture_Pants;
782 int loc_Texture_Shirt;
783 int loc_Texture_FogHeightTexture;
784 int loc_Texture_FogMask;
785 int loc_Texture_Lightmap;
786 int loc_Texture_Deluxemap;
787 int loc_Texture_Attenuation;
788 int loc_Texture_Cube;
789 int loc_Texture_Refraction;
790 int loc_Texture_Reflection;
791 int loc_Texture_ShadowMap2D;
792 int loc_Texture_CubeProjection;
793 int loc_Texture_ScreenDepth;
794 int loc_Texture_ScreenNormalMap;
795 int loc_Texture_ScreenDiffuse;
796 int loc_Texture_ScreenSpecular;
797 int loc_Texture_ReflectMask;
798 int loc_Texture_ReflectCube;
799 int loc_Texture_BounceGrid;
801 int loc_BloomBlur_Parameters;
803 int loc_Color_Ambient;
804 int loc_Color_Diffuse;
805 int loc_Color_Specular;
809 int loc_DeferredColor_Ambient;
810 int loc_DeferredColor_Diffuse;
811 int loc_DeferredColor_Specular;
812 int loc_DeferredMod_Diffuse;
813 int loc_DeferredMod_Specular;
814 int loc_DistortScaleRefractReflect;
817 int loc_FogHeightFade;
819 int loc_FogPlaneViewDist;
820 int loc_FogRangeRecip;
823 int loc_LightPosition;
824 int loc_OffsetMapping_ScaleSteps;
826 int loc_ReflectColor;
827 int loc_ReflectFactor;
828 int loc_ReflectOffset;
829 int loc_RefractColor;
831 int loc_ScreenCenterRefractReflect;
832 int loc_ScreenScaleRefractReflect;
833 int loc_ScreenToDepth;
834 int loc_ShadowMap_Parameters;
835 int loc_ShadowMap_TextureScale;
836 int loc_SpecularPower;
841 int loc_ViewTintColor;
843 int loc_ModelToLight;
845 int loc_BackgroundTexMatrix;
846 int loc_ModelViewProjectionMatrix;
847 int loc_ModelViewMatrix;
848 int loc_PixelToScreenTexCoord;
849 int loc_ModelToReflectCube;
850 int loc_ShadowMapMatrix;
851 int loc_BloomColorSubtract;
852 int loc_NormalmapScrollBlend;
853 int loc_BounceGridMatrix;
854 int loc_BounceGridIntensity;
856 r_glsl_permutation_t;
858 #define SHADERPERMUTATION_HASHSIZE 256
861 // non-degradable "lightweight" shader parameters to keep the permutations simpler
862 // these can NOT degrade! only use for simple stuff
865 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
866 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
867 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
868 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
869 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
870 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5, ///< postprocess uservec4 is enabled
871 SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
873 #define SHADERSTATICPARMS_COUNT 7
875 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
876 static int shaderstaticparms_count = 0;
878 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
879 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
880 qboolean R_CompileShader_CheckStaticParms(void)
882 static int r_compileshader_staticparms_save[1];
883 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
884 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
887 if (r_glsl_saturation_redcompensate.integer)
888 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
889 if (r_glsl_vertextextureblend_usebothalphas.integer)
890 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
891 if (r_shadow_glossexact.integer)
892 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
893 if (r_glsl_postprocess.integer)
895 if (r_glsl_postprocess_uservec1_enable.integer)
896 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
897 if (r_glsl_postprocess_uservec2_enable.integer)
898 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
899 if (r_glsl_postprocess_uservec3_enable.integer)
900 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
901 if (r_glsl_postprocess_uservec4_enable.integer)
902 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
904 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
907 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
908 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
909 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
911 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
912 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
914 shaderstaticparms_count = 0;
917 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
918 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
919 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
920 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
921 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
922 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
923 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
926 /// information about each possible shader permutation
927 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
928 /// currently selected permutation
929 r_glsl_permutation_t *r_glsl_permutation;
930 /// storage for permutations linked in the hash table
931 memexpandablearray_t r_glsl_permutationarray;
933 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 //unsigned int hashdepth = 0;
936 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
937 r_glsl_permutation_t *p;
938 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940 if (p->mode == mode && p->permutation == permutation)
942 //if (hashdepth > 10)
943 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
948 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950 p->permutation = permutation;
951 p->hashnext = r_glsl_permutationhash[mode][hashindex];
952 r_glsl_permutationhash[mode][hashindex] = p;
953 //if (hashdepth > 10)
954 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
958 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
961 if (!filename || !filename[0])
963 if (!strcmp(filename, "glsl/default.glsl"))
965 if (!glslshaderstring)
967 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
968 if (glslshaderstring)
969 Con_DPrintf("Loading shaders from file %s...\n", filename);
971 glslshaderstring = (char *)builtinshaderstring;
973 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
974 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
977 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980 if (printfromdisknotice)
981 Con_DPrintf("from disk %s... ", filename);
987 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
991 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
992 char *vertexstring, *geometrystring, *fragmentstring;
993 char permutationname[256];
994 int vertstrings_count = 0;
995 int geomstrings_count = 0;
996 int fragstrings_count = 0;
997 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
998 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
999 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1006 permutationname[0] = 0;
1007 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
1008 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1009 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1014 if(vid.support.gl20shaders130)
1016 vertstrings_list[vertstrings_count++] = "#version 130\n";
1017 geomstrings_list[geomstrings_count++] = "#version 130\n";
1018 fragstrings_list[fragstrings_count++] = "#version 130\n";
1019 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1020 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1021 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1024 // the first pretext is which type of shader to compile as
1025 // (later these will all be bound together as a program object)
1026 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1027 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1028 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030 // the second pretext is the mode (for example a light source)
1031 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1032 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1033 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1034 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036 // now add all the permutation pretexts
1037 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039 if (permutation & (1<<i))
1041 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1042 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1043 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1044 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1048 // keep line numbers correct
1049 vertstrings_list[vertstrings_count++] = "\n";
1050 geomstrings_list[geomstrings_count++] = "\n";
1051 fragstrings_list[fragstrings_count++] = "\n";
1056 R_CompileShader_AddStaticParms(mode, permutation);
1057 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058 vertstrings_count += shaderstaticparms_count;
1059 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060 geomstrings_count += shaderstaticparms_count;
1061 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062 fragstrings_count += shaderstaticparms_count;
1064 // now append the shader text itself
1065 vertstrings_list[vertstrings_count++] = vertexstring;
1066 geomstrings_list[geomstrings_count++] = geometrystring;
1067 fragstrings_list[fragstrings_count++] = fragmentstring;
1069 // if any sources were NULL, clear the respective list
1071 vertstrings_count = 0;
1072 if (!geometrystring)
1073 geomstrings_count = 0;
1074 if (!fragmentstring)
1075 fragstrings_count = 0;
1077 // compile the shader program
1078 if (vertstrings_count + geomstrings_count + fragstrings_count)
1079 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1083 qglUseProgram(p->program);CHECKGLERROR
1084 // look up all the uniform variable names we care about, so we don't
1085 // have to look them up every time we set them
1087 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1088 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1089 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1090 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1091 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1092 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1093 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1094 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1095 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1096 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1097 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1098 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1099 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1100 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1101 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1102 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1103 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1104 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1105 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1106 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1107 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1108 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1109 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1110 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1111 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1112 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1113 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1114 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1115 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1116 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1117 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1118 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1119 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1120 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1121 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1122 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1123 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1124 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1125 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1126 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1127 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1128 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1129 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1130 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1131 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1132 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1133 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1134 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1135 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1136 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1137 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1138 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1139 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1140 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1141 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1142 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1143 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1144 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1145 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1146 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1147 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1148 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1149 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1150 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1151 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1152 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1153 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1154 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1155 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1156 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1157 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1158 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1159 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1160 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1161 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1162 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1163 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1164 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1165 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1166 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1167 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1168 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1169 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1170 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1171 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1172 // initialize the samplers to refer to the texture units we use
1173 p->tex_Texture_First = -1;
1174 p->tex_Texture_Second = -1;
1175 p->tex_Texture_GammaRamps = -1;
1176 p->tex_Texture_Normal = -1;
1177 p->tex_Texture_Color = -1;
1178 p->tex_Texture_Gloss = -1;
1179 p->tex_Texture_Glow = -1;
1180 p->tex_Texture_SecondaryNormal = -1;
1181 p->tex_Texture_SecondaryColor = -1;
1182 p->tex_Texture_SecondaryGloss = -1;
1183 p->tex_Texture_SecondaryGlow = -1;
1184 p->tex_Texture_Pants = -1;
1185 p->tex_Texture_Shirt = -1;
1186 p->tex_Texture_FogHeightTexture = -1;
1187 p->tex_Texture_FogMask = -1;
1188 p->tex_Texture_Lightmap = -1;
1189 p->tex_Texture_Deluxemap = -1;
1190 p->tex_Texture_Attenuation = -1;
1191 p->tex_Texture_Cube = -1;
1192 p->tex_Texture_Refraction = -1;
1193 p->tex_Texture_Reflection = -1;
1194 p->tex_Texture_ShadowMap2D = -1;
1195 p->tex_Texture_CubeProjection = -1;
1196 p->tex_Texture_ScreenDepth = -1;
1197 p->tex_Texture_ScreenNormalMap = -1;
1198 p->tex_Texture_ScreenDiffuse = -1;
1199 p->tex_Texture_ScreenSpecular = -1;
1200 p->tex_Texture_ReflectMask = -1;
1201 p->tex_Texture_ReflectCube = -1;
1202 p->tex_Texture_BounceGrid = -1;
1204 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1205 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1206 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1207 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1208 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1209 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1210 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1211 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1212 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1213 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1214 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1215 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1216 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1217 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1218 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1219 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1220 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1221 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1222 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1223 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1224 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1225 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1226 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1227 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1228 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1229 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1230 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1231 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1232 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1233 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1235 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1238 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1242 Mem_Free(vertexstring);
1244 Mem_Free(geometrystring);
1246 Mem_Free(fragmentstring);
1249 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1251 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1252 if (r_glsl_permutation != perm)
1254 r_glsl_permutation = perm;
1255 if (!r_glsl_permutation->program)
1257 if (!r_glsl_permutation->compiled)
1258 R_GLSL_CompilePermutation(perm, mode, permutation);
1259 if (!r_glsl_permutation->program)
1261 // remove features until we find a valid permutation
1263 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1265 // reduce i more quickly whenever it would not remove any bits
1266 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1267 if (!(permutation & j))
1270 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271 if (!r_glsl_permutation->compiled)
1272 R_GLSL_CompilePermutation(perm, mode, permutation);
1273 if (r_glsl_permutation->program)
1276 if (i >= SHADERPERMUTATION_COUNT)
1278 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1279 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1280 qglUseProgram(0);CHECKGLERROR
1281 return; // no bit left to clear, entire mode is broken
1286 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1288 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1289 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1290 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1297 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1298 extern D3DCAPS9 vid_d3d9caps;
1301 struct r_hlsl_permutation_s;
1302 typedef struct r_hlsl_permutation_s
1304 /// hash lookup data
1305 struct r_hlsl_permutation_s *hashnext;
1307 unsigned int permutation;
1309 /// indicates if we have tried compiling this permutation already
1311 /// NULL if compilation failed
1312 IDirect3DVertexShader9 *vertexshader;
1313 IDirect3DPixelShader9 *pixelshader;
1315 r_hlsl_permutation_t;
1317 typedef enum D3DVSREGISTER_e
1319 D3DVSREGISTER_TexMatrix = 0, // float4x4
1320 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1321 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1322 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1323 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1324 D3DVSREGISTER_ModelToLight = 20, // float4x4
1325 D3DVSREGISTER_EyePosition = 24,
1326 D3DVSREGISTER_FogPlane = 25,
1327 D3DVSREGISTER_LightDir = 26,
1328 D3DVSREGISTER_LightPosition = 27,
1332 typedef enum D3DPSREGISTER_e
1334 D3DPSREGISTER_Alpha = 0,
1335 D3DPSREGISTER_BloomBlur_Parameters = 1,
1336 D3DPSREGISTER_ClientTime = 2,
1337 D3DPSREGISTER_Color_Ambient = 3,
1338 D3DPSREGISTER_Color_Diffuse = 4,
1339 D3DPSREGISTER_Color_Specular = 5,
1340 D3DPSREGISTER_Color_Glow = 6,
1341 D3DPSREGISTER_Color_Pants = 7,
1342 D3DPSREGISTER_Color_Shirt = 8,
1343 D3DPSREGISTER_DeferredColor_Ambient = 9,
1344 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1345 D3DPSREGISTER_DeferredColor_Specular = 11,
1346 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1347 D3DPSREGISTER_DeferredMod_Specular = 13,
1348 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1349 D3DPSREGISTER_EyePosition = 15, // unused
1350 D3DPSREGISTER_FogColor = 16,
1351 D3DPSREGISTER_FogHeightFade = 17,
1352 D3DPSREGISTER_FogPlane = 18,
1353 D3DPSREGISTER_FogPlaneViewDist = 19,
1354 D3DPSREGISTER_FogRangeRecip = 20,
1355 D3DPSREGISTER_LightColor = 21,
1356 D3DPSREGISTER_LightDir = 22, // unused
1357 D3DPSREGISTER_LightPosition = 23,
1358 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1359 D3DPSREGISTER_PixelSize = 25,
1360 D3DPSREGISTER_ReflectColor = 26,
1361 D3DPSREGISTER_ReflectFactor = 27,
1362 D3DPSREGISTER_ReflectOffset = 28,
1363 D3DPSREGISTER_RefractColor = 29,
1364 D3DPSREGISTER_Saturation = 30,
1365 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1366 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1367 D3DPSREGISTER_ScreenToDepth = 33,
1368 D3DPSREGISTER_ShadowMap_Parameters = 34,
1369 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1370 D3DPSREGISTER_SpecularPower = 36,
1371 D3DPSREGISTER_UserVec1 = 37,
1372 D3DPSREGISTER_UserVec2 = 38,
1373 D3DPSREGISTER_UserVec3 = 39,
1374 D3DPSREGISTER_UserVec4 = 40,
1375 D3DPSREGISTER_ViewTintColor = 41,
1376 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1377 D3DPSREGISTER_BloomColorSubtract = 43,
1378 D3DPSREGISTER_ViewToLight = 44, // float4x4
1379 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1380 D3DPSREGISTER_NormalmapScrollBlend = 52,
1385 /// information about each possible shader permutation
1386 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1387 /// currently selected permutation
1388 r_hlsl_permutation_t *r_hlsl_permutation;
1389 /// storage for permutations linked in the hash table
1390 memexpandablearray_t r_hlsl_permutationarray;
1392 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1394 //unsigned int hashdepth = 0;
1395 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1396 r_hlsl_permutation_t *p;
1397 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1399 if (p->mode == mode && p->permutation == permutation)
1401 //if (hashdepth > 10)
1402 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1407 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1409 p->permutation = permutation;
1410 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1411 r_hlsl_permutationhash[mode][hashindex] = p;
1412 //if (hashdepth > 10)
1413 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1417 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 if (!filename || !filename[0])
1422 if (!strcmp(filename, "hlsl/default.hlsl"))
1424 if (!hlslshaderstring)
1426 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1427 if (hlslshaderstring)
1428 Con_DPrintf("Loading shaders from file %s...\n", filename);
1430 hlslshaderstring = (char *)builtinhlslshaderstring;
1432 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1433 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1434 return shaderstring;
1436 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439 if (printfromdisknotice)
1440 Con_DPrintf("from disk %s... ", filename);
1441 return shaderstring;
1443 return shaderstring;
1447 //#include <d3dx9shader.h>
1448 //#include <d3dx9mesh.h>
1450 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1452 DWORD *vsbin = NULL;
1453 DWORD *psbin = NULL;
1454 fs_offset_t vsbinsize;
1455 fs_offset_t psbinsize;
1456 // IDirect3DVertexShader9 *vs = NULL;
1457 // IDirect3DPixelShader9 *ps = NULL;
1458 ID3DXBuffer *vslog = NULL;
1459 ID3DXBuffer *vsbuffer = NULL;
1460 ID3DXConstantTable *vsconstanttable = NULL;
1461 ID3DXBuffer *pslog = NULL;
1462 ID3DXBuffer *psbuffer = NULL;
1463 ID3DXConstantTable *psconstanttable = NULL;
1466 char temp[MAX_INPUTLINE];
1467 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1468 qboolean debugshader = gl_paranoid.integer != 0;
1469 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1470 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1474 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1476 if ((!vsbin && vertstring) || (!psbin && fragstring))
1478 const char* dllnames_d3dx9 [] =
1502 dllhandle_t d3dx9_dll = NULL;
1503 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1504 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1505 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506 dllfunction_t d3dx9_dllfuncs[] =
1508 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1509 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1510 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1513 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1515 DWORD shaderflags = 0;
1517 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1518 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1519 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1520 if (vertstring && vertstring[0])
1524 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1525 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1526 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1527 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1533 vsbinsize = vsbuffer->GetBufferSize();
1534 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1535 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1536 vsbuffer->Release();
1540 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1541 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1545 if (fragstring && fragstring[0])
1549 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1550 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1551 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1552 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1558 psbinsize = psbuffer->GetBufferSize();
1559 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1560 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1561 psbuffer->Release();
1565 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1566 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1570 Sys_UnloadLibrary(&d3dx9_dll);
1573 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1577 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1578 if (FAILED(vsresult))
1579 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1580 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1581 if (FAILED(psresult))
1582 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1584 // free the shader data
1585 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1586 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1592 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1593 int vertstring_length = 0;
1594 int geomstring_length = 0;
1595 int fragstring_length = 0;
1597 char *vertexstring, *geometrystring, *fragmentstring;
1598 char *vertstring, *geomstring, *fragstring;
1599 char permutationname[256];
1600 char cachename[256];
1601 int vertstrings_count = 0;
1602 int geomstrings_count = 0;
1603 int fragstrings_count = 0;
1604 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1605 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1606 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1611 p->vertexshader = NULL;
1612 p->pixelshader = NULL;
1614 permutationname[0] = 0;
1616 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1617 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1618 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1620 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1621 strlcat(cachename, "hlsl/", sizeof(cachename));
1623 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1624 vertstrings_count = 0;
1625 geomstrings_count = 0;
1626 fragstrings_count = 0;
1627 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1628 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1629 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1631 // the first pretext is which type of shader to compile as
1632 // (later these will all be bound together as a program object)
1633 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1634 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1635 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1637 // the second pretext is the mode (for example a light source)
1638 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1639 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1640 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1641 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1642 strlcat(cachename, modeinfo->name, sizeof(cachename));
1644 // now add all the permutation pretexts
1645 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1647 if (permutation & (1<<i))
1649 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1650 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1651 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1652 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1653 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1657 // keep line numbers correct
1658 vertstrings_list[vertstrings_count++] = "\n";
1659 geomstrings_list[geomstrings_count++] = "\n";
1660 fragstrings_list[fragstrings_count++] = "\n";
1665 R_CompileShader_AddStaticParms(mode, permutation);
1666 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667 vertstrings_count += shaderstaticparms_count;
1668 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669 geomstrings_count += shaderstaticparms_count;
1670 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671 fragstrings_count += shaderstaticparms_count;
1673 // replace spaces in the cachename with _ characters
1674 for (i = 0;cachename[i];i++)
1675 if (cachename[i] == ' ')
1678 // now append the shader text itself
1679 vertstrings_list[vertstrings_count++] = vertexstring;
1680 geomstrings_list[geomstrings_count++] = geometrystring;
1681 fragstrings_list[fragstrings_count++] = fragmentstring;
1683 // if any sources were NULL, clear the respective list
1685 vertstrings_count = 0;
1686 if (!geometrystring)
1687 geomstrings_count = 0;
1688 if (!fragmentstring)
1689 fragstrings_count = 0;
1691 vertstring_length = 0;
1692 for (i = 0;i < vertstrings_count;i++)
1693 vertstring_length += strlen(vertstrings_list[i]);
1694 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1695 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1696 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1698 geomstring_length = 0;
1699 for (i = 0;i < geomstrings_count;i++)
1700 geomstring_length += strlen(geomstrings_list[i]);
1701 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1702 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1703 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1705 fragstring_length = 0;
1706 for (i = 0;i < fragstrings_count;i++)
1707 fragstring_length += strlen(fragstrings_list[i]);
1708 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1709 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1710 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1712 // try to load the cached shader, or generate one
1713 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1715 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1716 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1718 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1722 Mem_Free(vertstring);
1724 Mem_Free(geomstring);
1726 Mem_Free(fragstring);
1728 Mem_Free(vertexstring);
1730 Mem_Free(geometrystring);
1732 Mem_Free(fragmentstring);
1735 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1736 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1737 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);}
1738 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);}
1739 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);}
1740 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);}
1742 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1743 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1744 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);}
1745 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);}
1746 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);}
1747 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);}
1749 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1751 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1752 if (r_hlsl_permutation != perm)
1754 r_hlsl_permutation = perm;
1755 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757 if (!r_hlsl_permutation->compiled)
1758 R_HLSL_CompilePermutation(perm, mode, permutation);
1759 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1761 // remove features until we find a valid permutation
1763 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1765 // reduce i more quickly whenever it would not remove any bits
1766 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1767 if (!(permutation & j))
1770 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771 if (!r_hlsl_permutation->compiled)
1772 R_HLSL_CompilePermutation(perm, mode, permutation);
1773 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1776 if (i >= SHADERPERMUTATION_COUNT)
1778 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1779 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1780 return; // no bit left to clear, entire mode is broken
1784 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1785 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1787 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1788 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1789 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1793 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1795 DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1796 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1797 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1798 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1801 void R_GLSL_Restart_f(void)
1803 unsigned int i, limit;
1804 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1805 Mem_Free(glslshaderstring);
1806 glslshaderstring = NULL;
1807 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1808 Mem_Free(hlslshaderstring);
1809 hlslshaderstring = NULL;
1810 switch(vid.renderpath)
1812 case RENDERPATH_D3D9:
1815 r_hlsl_permutation_t *p;
1816 r_hlsl_permutation = NULL;
1817 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1818 for (i = 0;i < limit;i++)
1820 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1822 if (p->vertexshader)
1823 IDirect3DVertexShader9_Release(p->vertexshader);
1825 IDirect3DPixelShader9_Release(p->pixelshader);
1826 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1829 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1833 case RENDERPATH_D3D10:
1834 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836 case RENDERPATH_D3D11:
1837 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839 case RENDERPATH_GL20:
1840 case RENDERPATH_GLES2:
1842 r_glsl_permutation_t *p;
1843 r_glsl_permutation = NULL;
1844 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1845 for (i = 0;i < limit;i++)
1847 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1849 GL_Backend_FreeProgram(p->program);
1850 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1853 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1856 case RENDERPATH_GL13:
1857 case RENDERPATH_GL11:
1859 case RENDERPATH_SOFT:
1864 void R_GLSL_DumpShader_f(void)
1869 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1872 FS_Print(file, "/* The engine may define the following macros:\n");
1873 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1874 for (i = 0;i < SHADERMODE_COUNT;i++)
1875 FS_Print(file, glslshadermodeinfo[i].pretext);
1876 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1877 FS_Print(file, shaderpermutationinfo[i].pretext);
1878 FS_Print(file, "*/\n");
1879 FS_Print(file, builtinshaderstring);
1881 Con_Printf("glsl/default.glsl written\n");
1884 Con_Printf("failed to write to glsl/default.glsl\n");
1886 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1889 FS_Print(file, "/* The engine may define the following macros:\n");
1890 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1891 for (i = 0;i < SHADERMODE_COUNT;i++)
1892 FS_Print(file, hlslshadermodeinfo[i].pretext);
1893 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1894 FS_Print(file, shaderpermutationinfo[i].pretext);
1895 FS_Print(file, "*/\n");
1896 FS_Print(file, builtinhlslshaderstring);
1898 Con_Printf("hlsl/default.hlsl written\n");
1901 Con_Printf("failed to write to hlsl/default.hlsl\n");
1904 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1907 texturemode = GL_MODULATE;
1908 switch (vid.renderpath)
1910 case RENDERPATH_D3D9:
1912 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))));
1913 R_Mesh_TexBind(GL20TU_FIRST , first );
1914 R_Mesh_TexBind(GL20TU_SECOND, second);
1917 case RENDERPATH_D3D10:
1918 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1920 case RENDERPATH_D3D11:
1921 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1923 case RENDERPATH_GL20:
1924 case RENDERPATH_GLES2:
1925 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))));
1926 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1927 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1929 case RENDERPATH_GL13:
1930 R_Mesh_TexBind(0, first );
1931 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1932 R_Mesh_TexBind(1, second);
1934 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1936 case RENDERPATH_GL11:
1937 R_Mesh_TexBind(0, first );
1939 case RENDERPATH_SOFT:
1940 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))));
1941 R_Mesh_TexBind(GL20TU_FIRST , first );
1942 R_Mesh_TexBind(GL20TU_SECOND, second);
1947 void R_SetupShader_DepthOrShadow(void)
1949 switch (vid.renderpath)
1951 case RENDERPATH_D3D9:
1953 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1956 case RENDERPATH_D3D10:
1957 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959 case RENDERPATH_D3D11:
1960 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1962 case RENDERPATH_GL20:
1963 case RENDERPATH_GLES2:
1964 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1966 case RENDERPATH_GL13:
1967 R_Mesh_TexBind(0, 0);
1968 R_Mesh_TexBind(1, 0);
1970 case RENDERPATH_GL11:
1971 R_Mesh_TexBind(0, 0);
1973 case RENDERPATH_SOFT:
1974 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1979 void R_SetupShader_ShowDepth(void)
1981 switch (vid.renderpath)
1983 case RENDERPATH_D3D9:
1985 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1988 case RENDERPATH_D3D10:
1989 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991 case RENDERPATH_D3D11:
1992 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1994 case RENDERPATH_GL20:
1995 case RENDERPATH_GLES2:
1996 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1998 case RENDERPATH_GL13:
2000 case RENDERPATH_GL11:
2002 case RENDERPATH_SOFT:
2003 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
2008 extern qboolean r_shadow_usingdeferredprepass;
2009 extern cvar_t r_shadow_deferred_8bitrange;
2010 extern rtexture_t *r_shadow_attenuationgradienttexture;
2011 extern rtexture_t *r_shadow_attenuation2dtexture;
2012 extern rtexture_t *r_shadow_attenuation3dtexture;
2013 extern qboolean r_shadow_usingshadowmap2d;
2014 extern qboolean r_shadow_usingshadowmaportho;
2015 extern float r_shadow_shadowmap_texturescale[2];
2016 extern float r_shadow_shadowmap_parameters[4];
2017 extern qboolean r_shadow_shadowmapvsdct;
2018 extern qboolean r_shadow_shadowmapsampler;
2019 extern int r_shadow_shadowmappcf;
2020 extern rtexture_t *r_shadow_shadowmap2dtexture;
2021 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2022 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2023 extern matrix4x4_t r_shadow_shadowmapmatrix;
2024 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2025 extern int r_shadow_prepass_width;
2026 extern int r_shadow_prepass_height;
2027 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2028 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2029 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2030 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2031 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2033 #define BLENDFUNC_ALLOWS_COLORMOD 1
2034 #define BLENDFUNC_ALLOWS_FOG 2
2035 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2036 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2037 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2038 static int R_BlendFuncFlags(int src, int dst)
2042 // a blendfunc allows colormod if:
2043 // a) it can never keep the destination pixel invariant, or
2044 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2045 // this is to prevent unintended side effects from colormod
2047 // a blendfunc allows fog if:
2048 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2049 // this is to prevent unintended side effects from fog
2051 // these checks are the output of fogeval.pl
2053 r |= BLENDFUNC_ALLOWS_COLORMOD;
2054 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2055 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2056 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2057 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2058 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2059 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2060 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2061 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2062 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2063 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2064 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2065 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2066 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2067 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2068 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2069 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2070 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2071 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2072 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2073 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2074 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079 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)
2081 // select a permutation of the lighting shader appropriate to this
2082 // combination of texture, entity, light source, and fogging, only use the
2083 // minimum features necessary to avoid wasting rendering time in the
2084 // fragment shader on features that are not being used
2085 unsigned int permutation = 0;
2086 unsigned int mode = 0;
2088 static float dummy_colormod[3] = {1, 1, 1};
2089 float *colormod = rsurface.colormod;
2091 matrix4x4_t tempmatrix;
2092 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2093 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2094 permutation |= SHADERPERMUTATION_ALPHAKILL;
2095 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2096 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2097 if (rsurfacepass == RSURFPASS_BACKGROUND)
2099 // distorted background
2100 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2102 mode = SHADERMODE_WATER;
2103 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2105 // this is the right thing to do for wateralpha
2106 GL_BlendFunc(GL_ONE, GL_ZERO);
2107 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2111 // this is the right thing to do for entity alpha
2112 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2113 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2116 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2118 mode = SHADERMODE_REFRACTION;
2119 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2120 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2124 mode = SHADERMODE_GENERIC;
2125 permutation |= SHADERPERMUTATION_DIFFUSE;
2126 GL_BlendFunc(GL_ONE, GL_ZERO);
2127 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2130 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2132 if (r_glsl_offsetmapping.integer)
2134 switch(rsurface.texture->offsetmapping)
2136 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2137 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2138 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2139 case OFFSETMAPPING_OFF: break;
2142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2144 // normalmap (deferred prepass), may use alpha test on diffuse
2145 mode = SHADERMODE_DEFERREDGEOMETRY;
2146 GL_BlendFunc(GL_ONE, GL_ZERO);
2147 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2149 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2151 if (r_glsl_offsetmapping.integer)
2153 switch(rsurface.texture->offsetmapping)
2155 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2156 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2157 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2158 case OFFSETMAPPING_OFF: break;
2161 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2162 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2164 mode = SHADERMODE_LIGHTSOURCE;
2165 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2166 permutation |= SHADERPERMUTATION_CUBEFILTER;
2167 if (diffusescale > 0)
2168 permutation |= SHADERPERMUTATION_DIFFUSE;
2169 if (specularscale > 0)
2170 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2171 if (r_refdef.fogenabled)
2172 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2173 if (rsurface.texture->colormapping)
2174 permutation |= SHADERPERMUTATION_COLORMAPPING;
2175 if (r_shadow_usingshadowmap2d)
2177 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2178 if(r_shadow_shadowmapvsdct)
2179 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2181 if (r_shadow_shadowmapsampler)
2182 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2183 if (r_shadow_shadowmappcf > 1)
2184 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2185 else if (r_shadow_shadowmappcf)
2186 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2188 if (rsurface.texture->reflectmasktexture)
2189 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2190 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2191 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2193 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2195 if (r_glsl_offsetmapping.integer)
2197 switch(rsurface.texture->offsetmapping)
2199 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202 case OFFSETMAPPING_OFF: break;
2205 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207 // unshaded geometry (fullbright or ambient model lighting)
2208 mode = SHADERMODE_FLATCOLOR;
2209 ambientscale = diffusescale = specularscale = 0;
2210 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2211 permutation |= SHADERPERMUTATION_GLOW;
2212 if (r_refdef.fogenabled)
2213 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2214 if (rsurface.texture->colormapping)
2215 permutation |= SHADERPERMUTATION_COLORMAPPING;
2216 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2218 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2219 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2221 if (r_shadow_shadowmapsampler)
2222 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2223 if (r_shadow_shadowmappcf > 1)
2224 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2225 else if (r_shadow_shadowmappcf)
2226 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2228 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2229 permutation |= SHADERPERMUTATION_REFLECTION;
2230 if (rsurface.texture->reflectmasktexture)
2231 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2232 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2233 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2235 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2237 if (r_glsl_offsetmapping.integer)
2239 switch(rsurface.texture->offsetmapping)
2241 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2242 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2244 case OFFSETMAPPING_OFF: break;
2247 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2248 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2249 // directional model lighting
2250 mode = SHADERMODE_LIGHTDIRECTION;
2251 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252 permutation |= SHADERPERMUTATION_GLOW;
2253 permutation |= SHADERPERMUTATION_DIFFUSE;
2254 if (specularscale > 0)
2255 permutation |= SHADERPERMUTATION_SPECULAR;
2256 if (r_refdef.fogenabled)
2257 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2258 if (rsurface.texture->colormapping)
2259 permutation |= SHADERPERMUTATION_COLORMAPPING;
2260 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2262 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2263 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265 if (r_shadow_shadowmapsampler)
2266 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2267 if (r_shadow_shadowmappcf > 1)
2268 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2269 else if (r_shadow_shadowmappcf)
2270 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2272 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2273 permutation |= SHADERPERMUTATION_REFLECTION;
2274 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2275 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2276 if (rsurface.texture->reflectmasktexture)
2277 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278 if (r_shadow_bouncegridtexture)
2280 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2281 if (r_shadow_bouncegriddirectional)
2282 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2284 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2287 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2289 if (r_glsl_offsetmapping.integer)
2291 switch(rsurface.texture->offsetmapping)
2293 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296 case OFFSETMAPPING_OFF: break;
2299 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301 // ambient model lighting
2302 mode = SHADERMODE_LIGHTDIRECTION;
2303 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304 permutation |= SHADERPERMUTATION_GLOW;
2305 if (r_refdef.fogenabled)
2306 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2307 if (rsurface.texture->colormapping)
2308 permutation |= SHADERPERMUTATION_COLORMAPPING;
2309 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2312 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314 if (r_shadow_shadowmapsampler)
2315 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2316 if (r_shadow_shadowmappcf > 1)
2317 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2318 else if (r_shadow_shadowmappcf)
2319 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2322 permutation |= SHADERPERMUTATION_REFLECTION;
2323 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2324 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2325 if (rsurface.texture->reflectmasktexture)
2326 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2327 if (r_shadow_bouncegridtexture)
2329 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2330 if (r_shadow_bouncegriddirectional)
2331 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2334 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2338 if (r_glsl_offsetmapping.integer)
2340 switch(rsurface.texture->offsetmapping)
2342 case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2343 case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2344 case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2345 case OFFSETMAPPING_OFF: break;
2348 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2349 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2351 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2352 permutation |= SHADERPERMUTATION_GLOW;
2353 if (r_refdef.fogenabled)
2354 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2355 if (rsurface.texture->colormapping)
2356 permutation |= SHADERPERMUTATION_COLORMAPPING;
2357 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2359 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2360 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2362 if (r_shadow_shadowmapsampler)
2363 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2364 if (r_shadow_shadowmappcf > 1)
2365 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2366 else if (r_shadow_shadowmappcf)
2367 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2369 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2370 permutation |= SHADERPERMUTATION_REFLECTION;
2371 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2372 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2373 if (rsurface.texture->reflectmasktexture)
2374 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2375 if (FAKELIGHT_ENABLED)
2377 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2378 mode = SHADERMODE_FAKELIGHT;
2379 permutation |= SHADERPERMUTATION_DIFFUSE;
2380 if (specularscale > 0)
2381 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2383 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2385 // deluxemapping (light direction texture)
2386 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2387 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390 permutation |= SHADERPERMUTATION_DIFFUSE;
2391 if (specularscale > 0)
2392 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2396 // fake deluxemapping (uniform light direction in tangentspace)
2397 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2398 permutation |= SHADERPERMUTATION_DIFFUSE;
2399 if (specularscale > 0)
2400 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2402 else if (rsurface.uselightmaptexture)
2404 // ordinary lightmapping (q1bsp, q3bsp)
2405 mode = SHADERMODE_LIGHTMAP;
2409 // ordinary vertex coloring (q3bsp)
2410 mode = SHADERMODE_VERTEXCOLOR;
2412 if (r_shadow_bouncegridtexture)
2414 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2415 if (r_shadow_bouncegriddirectional)
2416 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2418 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2419 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2422 colormod = dummy_colormod;
2423 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2424 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2425 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2426 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2427 switch(vid.renderpath)
2429 case RENDERPATH_D3D9:
2431 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);
2432 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2433 R_SetupShader_SetPermutationHLSL(mode, permutation);
2434 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2435 if (mode == SHADERMODE_LIGHTSOURCE)
2437 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2438 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2442 if (mode == SHADERMODE_LIGHTDIRECTION)
2444 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2447 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2448 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2449 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2450 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2451 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2453 if (mode == SHADERMODE_LIGHTSOURCE)
2455 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2456 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2457 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2458 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2459 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2461 // additive passes are only darkened by fog, not tinted
2462 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2463 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2467 if (mode == SHADERMODE_FLATCOLOR)
2469 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2471 else if (mode == SHADERMODE_LIGHTDIRECTION)
2473 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]);
2474 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2475 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);
2476 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);
2477 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2478 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2479 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2483 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2484 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2485 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);
2486 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);
2487 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2489 // additive passes are only darkened by fog, not tinted
2490 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2491 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2493 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2494 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);
2495 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2496 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2497 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2499 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2500 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2501 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2502 if (mode == SHADERMODE_WATER)
2503 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2505 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2506 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2508 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));
2509 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2510 if (rsurface.texture->pantstexture)
2511 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2513 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2514 if (rsurface.texture->shirttexture)
2515 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2517 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2518 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2519 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2520 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2521 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2522 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2523 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2524 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2525 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2526 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2528 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2529 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2531 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2532 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2533 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2534 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2535 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2536 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2537 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2538 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2539 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2540 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2541 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2542 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2543 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2544 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2545 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2546 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2547 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2548 if (rsurfacepass == RSURFPASS_BACKGROUND)
2550 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2551 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2552 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2556 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2558 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2559 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2560 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2561 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2562 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2564 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2565 if (rsurface.rtlight)
2567 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2568 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2573 case RENDERPATH_D3D10:
2574 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2576 case RENDERPATH_D3D11:
2577 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2579 case RENDERPATH_GL20:
2580 case RENDERPATH_GLES2:
2581 if (!vid.useinterleavedarrays)
2583 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);
2584 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2585 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2586 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2587 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2588 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2589 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2590 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2594 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);
2595 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2597 R_SetupShader_SetPermutationGLSL(mode, permutation);
2598 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2599 if (mode == SHADERMODE_LIGHTSOURCE)
2601 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2602 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2603 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2604 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2605 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2606 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);
2608 // additive passes are only darkened by fog, not tinted
2609 if (r_glsl_permutation->loc_FogColor >= 0)
2610 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2611 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2615 if (mode == SHADERMODE_FLATCOLOR)
2617 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2619 else if (mode == SHADERMODE_LIGHTDIRECTION)
2621 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]);
2622 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]);
2623 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);
2624 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);
2625 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);
2626 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]);
2627 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]);
2631 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]);
2632 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]);
2633 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);
2634 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);
2635 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);
2637 // additive passes are only darkened by fog, not tinted
2638 if (r_glsl_permutation->loc_FogColor >= 0)
2640 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2641 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2643 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2645 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);
2646 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]);
2647 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]);
2648 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]);
2649 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]);
2650 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2651 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2652 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2653 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]);
2655 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2656 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2657 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2658 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]);
2659 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]);
2661 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2662 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));
2663 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2664 if (r_glsl_permutation->loc_Color_Pants >= 0)
2666 if (rsurface.texture->pantstexture)
2667 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2669 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2671 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2673 if (rsurface.texture->shirttexture)
2674 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2676 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2678 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]);
2679 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2680 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2681 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2682 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2683 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2684 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2688 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]);
2689 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2690 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);}
2691 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2693 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2694 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2695 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2696 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2697 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2698 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2699 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2700 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2701 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2702 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2703 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2704 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2705 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2706 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2707 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);
2708 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2709 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2710 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2711 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2712 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2713 if (rsurfacepass == RSURFPASS_BACKGROUND)
2715 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);
2716 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);
2717 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);
2721 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);
2723 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2724 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2725 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2726 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2727 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2729 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2730 if (rsurface.rtlight)
2732 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2733 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2736 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2739 case RENDERPATH_GL13:
2740 case RENDERPATH_GL11:
2742 case RENDERPATH_SOFT:
2743 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);
2744 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2745 R_SetupShader_SetPermutationSoft(mode, permutation);
2746 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2747 if (mode == SHADERMODE_LIGHTSOURCE)
2749 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2750 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2751 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2752 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2753 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2756 // additive passes are only darkened by fog, not tinted
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2758 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2762 if (mode == SHADERMODE_FLATCOLOR)
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2766 else if (mode == SHADERMODE_LIGHTDIRECTION)
2768 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]);
2769 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2770 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);
2771 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);
2772 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2773 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]);
2774 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2778 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2779 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2780 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);
2781 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);
2782 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2784 // additive passes are only darkened by fog, not tinted
2785 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2786 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2788 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2789 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);
2790 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2791 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2792 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]);
2793 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]);
2794 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2795 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2796 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2797 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2799 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2800 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2801 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2802 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2803 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]);
2805 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2806 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));
2807 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2808 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2810 if (rsurface.texture->pantstexture)
2811 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2813 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2815 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2817 if (rsurface.texture->shirttexture)
2818 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2820 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2822 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2823 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2824 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2825 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2826 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2827 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2828 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2829 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2830 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2832 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2833 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2835 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2836 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2837 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2838 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2839 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2840 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2841 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2842 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2843 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2844 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2845 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2846 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2847 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2848 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2849 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2850 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2851 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2852 if (rsurfacepass == RSURFPASS_BACKGROUND)
2854 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2855 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2856 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2860 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2862 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2863 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2864 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2865 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2866 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2868 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2869 if (rsurface.rtlight)
2871 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2872 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2879 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2881 // select a permutation of the lighting shader appropriate to this
2882 // combination of texture, entity, light source, and fogging, only use the
2883 // minimum features necessary to avoid wasting rendering time in the
2884 // fragment shader on features that are not being used
2885 unsigned int permutation = 0;
2886 unsigned int mode = 0;
2887 const float *lightcolorbase = rtlight->currentcolor;
2888 float ambientscale = rtlight->ambientscale;
2889 float diffusescale = rtlight->diffusescale;
2890 float specularscale = rtlight->specularscale;
2891 // this is the location of the light in view space
2892 vec3_t viewlightorigin;
2893 // this transforms from view space (camera) to light space (cubemap)
2894 matrix4x4_t viewtolight;
2895 matrix4x4_t lighttoview;
2896 float viewtolight16f[16];
2897 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2899 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2900 if (rtlight->currentcubemap != r_texture_whitecube)
2901 permutation |= SHADERPERMUTATION_CUBEFILTER;
2902 if (diffusescale > 0)
2903 permutation |= SHADERPERMUTATION_DIFFUSE;
2904 if (specularscale > 0 && r_shadow_gloss.integer > 0)
2905 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2906 if (r_shadow_usingshadowmap2d)
2908 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2909 if (r_shadow_shadowmapvsdct)
2910 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2912 if (r_shadow_shadowmapsampler)
2913 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2914 if (r_shadow_shadowmappcf > 1)
2915 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2916 else if (r_shadow_shadowmappcf)
2917 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2919 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2920 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2921 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2922 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2923 switch(vid.renderpath)
2925 case RENDERPATH_D3D9:
2927 R_SetupShader_SetPermutationHLSL(mode, permutation);
2928 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2929 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2930 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2931 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2932 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2933 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2934 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2935 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2936 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2937 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2939 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2940 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2941 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2942 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2943 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2944 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2947 case RENDERPATH_D3D10:
2948 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2950 case RENDERPATH_D3D11:
2951 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2953 case RENDERPATH_GL20:
2954 case RENDERPATH_GLES2:
2955 R_SetupShader_SetPermutationGLSL(mode, permutation);
2956 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2957 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2958 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);
2959 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);
2960 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);
2961 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]);
2962 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]);
2963 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));
2964 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]);
2965 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2967 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2968 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2969 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2970 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2971 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2972 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2974 case RENDERPATH_GL13:
2975 case RENDERPATH_GL11:
2977 case RENDERPATH_SOFT:
2978 R_SetupShader_SetPermutationGLSL(mode, permutation);
2979 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2980 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2981 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2982 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2983 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2984 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2985 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]);
2986 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));
2987 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2988 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2990 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2991 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2992 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2993 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2994 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2995 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
3000 #define SKINFRAME_HASH 1024
3004 int loadsequence; // incremented each level change
3005 memexpandablearray_t array;
3006 skinframe_t *hash[SKINFRAME_HASH];
3009 r_skinframe_t r_skinframe;
3011 void R_SkinFrame_PrepareForPurge(void)
3013 r_skinframe.loadsequence++;
3014 // wrap it without hitting zero
3015 if (r_skinframe.loadsequence >= 200)
3016 r_skinframe.loadsequence = 1;
3019 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3023 // mark the skinframe as used for the purging code
3024 skinframe->loadsequence = r_skinframe.loadsequence;
3027 void R_SkinFrame_Purge(void)
3031 for (i = 0;i < SKINFRAME_HASH;i++)
3033 for (s = r_skinframe.hash[i];s;s = s->next)
3035 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3037 if (s->merged == s->base)
3039 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3040 R_PurgeTexture(s->stain );s->stain = NULL;
3041 R_PurgeTexture(s->merged);s->merged = NULL;
3042 R_PurgeTexture(s->base );s->base = NULL;
3043 R_PurgeTexture(s->pants );s->pants = NULL;
3044 R_PurgeTexture(s->shirt );s->shirt = NULL;
3045 R_PurgeTexture(s->nmap );s->nmap = NULL;
3046 R_PurgeTexture(s->gloss );s->gloss = NULL;
3047 R_PurgeTexture(s->glow );s->glow = NULL;
3048 R_PurgeTexture(s->fog );s->fog = NULL;
3049 R_PurgeTexture(s->reflect);s->reflect = NULL;
3050 s->loadsequence = 0;
3056 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3058 char basename[MAX_QPATH];
3060 Image_StripImageExtension(name, basename, sizeof(basename));
3062 if( last == NULL ) {
3064 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3065 item = r_skinframe.hash[hashindex];
3070 // linearly search through the hash bucket
3071 for( ; item ; item = item->next ) {
3072 if( !strcmp( item->basename, basename ) ) {
3079 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3083 char basename[MAX_QPATH];
3085 Image_StripImageExtension(name, basename, sizeof(basename));
3087 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3088 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3089 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3093 rtexture_t *dyntexture;
3094 // check whether its a dynamic texture
3095 dyntexture = CL_GetDynTexture( basename );
3096 if (!add && !dyntexture)
3098 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3099 memset(item, 0, sizeof(*item));
3100 strlcpy(item->basename, basename, sizeof(item->basename));
3101 item->base = dyntexture; // either NULL or dyntexture handle
3102 item->textureflags = textureflags;
3103 item->comparewidth = comparewidth;
3104 item->compareheight = compareheight;
3105 item->comparecrc = comparecrc;
3106 item->next = r_skinframe.hash[hashindex];
3107 r_skinframe.hash[hashindex] = item;
3109 else if( item->base == NULL )
3111 rtexture_t *dyntexture;
3112 // check whether its a dynamic texture
3113 // 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]
3114 dyntexture = CL_GetDynTexture( basename );
3115 item->base = dyntexture; // either NULL or dyntexture handle
3118 R_SkinFrame_MarkUsed(item);
3122 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3124 unsigned long long avgcolor[5], wsum; \
3132 for(pix = 0; pix < cnt; ++pix) \
3135 for(comp = 0; comp < 3; ++comp) \
3137 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3140 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3142 for(comp = 0; comp < 3; ++comp) \
3143 avgcolor[comp] += getpixel * w; \
3146 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3147 avgcolor[4] += getpixel; \
3149 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3151 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3152 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3153 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3154 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3157 extern cvar_t gl_picmip;
3158 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3161 unsigned char *pixels;
3162 unsigned char *bumppixels;
3163 unsigned char *basepixels = NULL;
3164 int basepixels_width = 0;
3165 int basepixels_height = 0;
3166 skinframe_t *skinframe;
3167 rtexture_t *ddsbase = NULL;
3168 qboolean ddshasalpha = false;
3169 float ddsavgcolor[4];
3170 char basename[MAX_QPATH];
3171 int miplevel = R_PicmipForFlags(textureflags);
3172 int savemiplevel = miplevel;
3175 if (cls.state == ca_dedicated)
3178 // return an existing skinframe if already loaded
3179 // if loading of the first image fails, don't make a new skinframe as it
3180 // would cause all future lookups of this to be missing
3181 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3182 if (skinframe && skinframe->base)
3185 Image_StripImageExtension(name, basename, sizeof(basename));
3187 // check for DDS texture file first
3188 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3190 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3191 if (basepixels == NULL)
3195 // FIXME handle miplevel
3197 if (developer_loading.integer)
3198 Con_Printf("loading skin \"%s\"\n", name);
3200 // we've got some pixels to store, so really allocate this new texture now
3202 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3203 skinframe->stain = NULL;
3204 skinframe->merged = NULL;
3205 skinframe->base = NULL;
3206 skinframe->pants = NULL;
3207 skinframe->shirt = NULL;
3208 skinframe->nmap = NULL;
3209 skinframe->gloss = NULL;
3210 skinframe->glow = NULL;
3211 skinframe->fog = NULL;
3212 skinframe->reflect = NULL;
3213 skinframe->hasalpha = false;
3217 skinframe->base = ddsbase;
3218 skinframe->hasalpha = ddshasalpha;
3219 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3220 if (r_loadfog && skinframe->hasalpha)
3221 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3222 //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]);
3226 basepixels_width = image_width;
3227 basepixels_height = image_height;
3228 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 ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3229 if (textureflags & TEXF_ALPHA)
3231 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3233 if (basepixels[j] < 255)
3235 skinframe->hasalpha = true;
3239 if (r_loadfog && skinframe->hasalpha)
3241 // has transparent pixels
3242 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3243 for (j = 0;j < image_width * image_height * 4;j += 4)
3248 pixels[j+3] = basepixels[j+3];
3250 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3254 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3255 //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]);
3256 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3257 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3258 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3259 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3264 mymiplevel = savemiplevel;
3265 if (r_loadnormalmap)
3266 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);
3267 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3269 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3270 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3271 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3272 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3275 // _norm is the name used by tenebrae and has been adopted as standard
3276 if (r_loadnormalmap && skinframe->nmap == NULL)
3278 mymiplevel = savemiplevel;
3279 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3281 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3285 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3287 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3288 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3289 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3291 Mem_Free(bumppixels);
3293 else if (r_shadow_bumpscale_basetexture.value > 0)
3295 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3296 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3297 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3300 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3301 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3304 // _luma is supported only for tenebrae compatibility
3305 // _glow is the preferred name
3306 mymiplevel = savemiplevel;
3307 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))))
3309 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3310 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3311 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3312 Mem_Free(pixels);pixels = NULL;
3315 mymiplevel = savemiplevel;
3316 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3318 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3319 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3320 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3325 mymiplevel = savemiplevel;
3326 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3328 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3329 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3330 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3335 mymiplevel = savemiplevel;
3336 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3338 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3339 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3340 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3345 mymiplevel = savemiplevel;
3346 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3348 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 ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3349 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3350 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3356 Mem_Free(basepixels);
3361 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3362 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3365 unsigned char *temp1, *temp2;
3366 skinframe_t *skinframe;
3368 if (cls.state == ca_dedicated)
3371 // if already loaded just return it, otherwise make a new skinframe
3372 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3373 if (skinframe && skinframe->base)
3376 skinframe->stain = NULL;
3377 skinframe->merged = NULL;
3378 skinframe->base = NULL;
3379 skinframe->pants = NULL;
3380 skinframe->shirt = NULL;
3381 skinframe->nmap = NULL;
3382 skinframe->gloss = NULL;
3383 skinframe->glow = NULL;
3384 skinframe->fog = NULL;
3385 skinframe->reflect = NULL;
3386 skinframe->hasalpha = false;
3388 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3392 if (developer_loading.integer)
3393 Con_Printf("loading 32bit skin \"%s\"\n", name);
3395 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3397 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3398 temp2 = temp1 + width * height * 4;
3399 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3400 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);
3403 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3404 if (textureflags & TEXF_ALPHA)
3406 for (i = 3;i < width * height * 4;i += 4)
3408 if (skindata[i] < 255)
3410 skinframe->hasalpha = true;
3414 if (r_loadfog && skinframe->hasalpha)
3416 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3417 memcpy(fogpixels, skindata, width * height * 4);
3418 for (i = 0;i < width * height * 4;i += 4)
3419 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3420 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3421 Mem_Free(fogpixels);
3425 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3426 //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]);
3431 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3435 skinframe_t *skinframe;
3437 if (cls.state == ca_dedicated)
3440 // if already loaded just return it, otherwise make a new skinframe
3441 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3442 if (skinframe && skinframe->base)
3445 skinframe->stain = NULL;
3446 skinframe->merged = NULL;
3447 skinframe->base = NULL;
3448 skinframe->pants = NULL;
3449 skinframe->shirt = NULL;
3450 skinframe->nmap = NULL;
3451 skinframe->gloss = NULL;
3452 skinframe->glow = NULL;
3453 skinframe->fog = NULL;
3454 skinframe->reflect = NULL;
3455 skinframe->hasalpha = false;
3457 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3461 if (developer_loading.integer)
3462 Con_Printf("loading quake skin \"%s\"\n", name);
3464 // 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)
3465 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3466 memcpy(skinframe->qpixels, skindata, width*height);
3467 skinframe->qwidth = width;
3468 skinframe->qheight = height;
3471 for (i = 0;i < width * height;i++)
3472 featuresmask |= palette_featureflags[skindata[i]];
3474 skinframe->hasalpha = false;
3475 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3476 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3477 skinframe->qgeneratemerged = true;
3478 skinframe->qgeneratebase = skinframe->qhascolormapping;
3479 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3481 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3482 //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]);
3487 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3491 unsigned char *skindata;
3493 if (!skinframe->qpixels)
3496 if (!skinframe->qhascolormapping)
3497 colormapped = false;
3501 if (!skinframe->qgeneratebase)
3506 if (!skinframe->qgeneratemerged)
3510 width = skinframe->qwidth;
3511 height = skinframe->qheight;
3512 skindata = skinframe->qpixels;
3514 if (skinframe->qgeneratenmap)
3516 unsigned char *temp1, *temp2;
3517 skinframe->qgeneratenmap = false;
3518 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3519 temp2 = temp1 + width * height * 4;
3520 // use either a custom palette or the quake palette
3521 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3522 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3523 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);
3527 if (skinframe->qgenerateglow)
3529 skinframe->qgenerateglow = false;
3530 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3535 skinframe->qgeneratebase = false;
3536 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);
3537 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3538 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3542 skinframe->qgeneratemerged = false;
3543 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);
3546 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3548 Mem_Free(skinframe->qpixels);
3549 skinframe->qpixels = NULL;
3553 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)
3556 skinframe_t *skinframe;
3558 if (cls.state == ca_dedicated)
3561 // if already loaded just return it, otherwise make a new skinframe
3562 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3563 if (skinframe && skinframe->base)
3566 skinframe->stain = NULL;
3567 skinframe->merged = NULL;
3568 skinframe->base = NULL;
3569 skinframe->pants = NULL;
3570 skinframe->shirt = NULL;
3571 skinframe->nmap = NULL;
3572 skinframe->gloss = NULL;
3573 skinframe->glow = NULL;
3574 skinframe->fog = NULL;
3575 skinframe->reflect = NULL;
3576 skinframe->hasalpha = false;
3578 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3582 if (developer_loading.integer)
3583 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3585 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3586 if (textureflags & TEXF_ALPHA)
3588 for (i = 0;i < width * height;i++)
3590 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3592 skinframe->hasalpha = true;
3596 if (r_loadfog && skinframe->hasalpha)
3597 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3600 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3601 //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]);
3606 skinframe_t *R_SkinFrame_LoadMissing(void)
3608 skinframe_t *skinframe;
3610 if (cls.state == ca_dedicated)
3613 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3614 skinframe->stain = NULL;
3615 skinframe->merged = NULL;
3616 skinframe->base = NULL;
3617 skinframe->pants = NULL;
3618 skinframe->shirt = NULL;
3619 skinframe->nmap = NULL;
3620 skinframe->gloss = NULL;
3621 skinframe->glow = NULL;
3622 skinframe->fog = NULL;
3623 skinframe->reflect = NULL;
3624 skinframe->hasalpha = false;
3626 skinframe->avgcolor[0] = rand() / RAND_MAX;
3627 skinframe->avgcolor[1] = rand() / RAND_MAX;
3628 skinframe->avgcolor[2] = rand() / RAND_MAX;
3629 skinframe->avgcolor[3] = 1;
3634 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3635 typedef struct suffixinfo_s
3638 qboolean flipx, flipy, flipdiagonal;
3641 static suffixinfo_t suffix[3][6] =
3644 {"px", false, false, false},
3645 {"nx", false, false, false},
3646 {"py", false, false, false},
3647 {"ny", false, false, false},
3648 {"pz", false, false, false},
3649 {"nz", false, false, false}
3652 {"posx", false, false, false},
3653 {"negx", false, false, false},
3654 {"posy", false, false, false},
3655 {"negy", false, false, false},
3656 {"posz", false, false, false},
3657 {"negz", false, false, false}
3660 {"rt", true, false, true},
3661 {"lf", false, true, true},
3662 {"ft", true, true, false},
3663 {"bk", false, false, false},
3664 {"up", true, false, true},
3665 {"dn", true, false, true}
3669 static int componentorder[4] = {0, 1, 2, 3};
3671 rtexture_t *R_LoadCubemap(const char *basename)
3673 int i, j, cubemapsize;
3674 unsigned char *cubemappixels, *image_buffer;
3675 rtexture_t *cubemaptexture;
3677 // must start 0 so the first loadimagepixels has no requested width/height
3679 cubemappixels = NULL;
3680 cubemaptexture = NULL;
3681 // keep trying different suffix groups (posx, px, rt) until one loads
3682 for (j = 0;j < 3 && !cubemappixels;j++)
3684 // load the 6 images in the suffix group
3685 for (i = 0;i < 6;i++)
3687 // generate an image name based on the base and and suffix
3688 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3690 if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3692 // an image loaded, make sure width and height are equal
3693 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3695 // if this is the first image to load successfully, allocate the cubemap memory
3696 if (!cubemappixels && image_width >= 1)
3698 cubemapsize = image_width;
3699 // note this clears to black, so unavailable sides are black
3700 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3702 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3704 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);
3707 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3709 Mem_Free(image_buffer);
3713 // if a cubemap loaded, upload it
3716 if (developer_loading.integer)
3717 Con_Printf("loading cubemap \"%s\"\n", basename);
3719 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, r_texture_sRGB_cubemap.integer != 0 ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3720 Mem_Free(cubemappixels);
3724 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3725 if (developer_loading.integer)
3727 Con_Printf("(tried tried images ");
3728 for (j = 0;j < 3;j++)
3729 for (i = 0;i < 6;i++)
3730 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3731 Con_Print(" and was unable to find any of them).\n");
3734 return cubemaptexture;
3737 rtexture_t *R_GetCubemap(const char *basename)
3740 for (i = 0;i < r_texture_numcubemaps;i++)
3741 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3742 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3743 if (i >= MAX_CUBEMAPS)
3744 return r_texture_whitecube;
3745 r_texture_numcubemaps++;
3746 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3747 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3748 return r_texture_cubemaps[i].texture;
3751 void R_FreeCubemaps(void)
3754 for (i = 0;i < r_texture_numcubemaps;i++)
3756 if (developer_loading.integer)
3757 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3758 if (r_texture_cubemaps[i].texture)
3759 R_FreeTexture(r_texture_cubemaps[i].texture);
3761 r_texture_numcubemaps = 0;
3764 void R_Main_FreeViewCache(void)
3766 if (r_refdef.viewcache.entityvisible)
3767 Mem_Free(r_refdef.viewcache.entityvisible);
3768 if (r_refdef.viewcache.world_pvsbits)
3769 Mem_Free(r_refdef.viewcache.world_pvsbits);
3770 if (r_refdef.viewcache.world_leafvisible)
3771 Mem_Free(r_refdef.viewcache.world_leafvisible);
3772 if (r_refdef.viewcache.world_surfacevisible)
3773 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3774 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3777 void R_Main_ResizeViewCache(void)
3779 int numentities = r_refdef.scene.numentities;
3780 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3781 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3782 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3783 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3784 if (r_refdef.viewcache.maxentities < numentities)
3786 r_refdef.viewcache.maxentities = numentities;
3787 if (r_refdef.viewcache.entityvisible)
3788 Mem_Free(r_refdef.viewcache.entityvisible);
3789 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3791 if (r_refdef.viewcache.world_numclusters != numclusters)
3793 r_refdef.viewcache.world_numclusters = numclusters;
3794 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3795 if (r_refdef.viewcache.world_pvsbits)
3796 Mem_Free(r_refdef.viewcache.world_pvsbits);
3797 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3799 if (r_refdef.viewcache.world_numleafs != numleafs)
3801 r_refdef.viewcache.world_numleafs = numleafs;
3802 if (r_refdef.viewcache.world_leafvisible)
3803 Mem_Free(r_refdef.viewcache.world_leafvisible);
3804 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3806 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3808 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3809 if (r_refdef.viewcache.world_surfacevisible)
3810 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3811 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3815 extern rtexture_t *loadingscreentexture;
3816 void gl_main_start(void)
3818 loadingscreentexture = NULL;
3819 r_texture_blanknormalmap = NULL;
3820 r_texture_white = NULL;
3821 r_texture_grey128 = NULL;
3822 r_texture_black = NULL;
3823 r_texture_whitecube = NULL;
3824 r_texture_normalizationcube = NULL;
3825 r_texture_fogattenuation = NULL;
3826 r_texture_fogheighttexture = NULL;
3827 r_texture_gammaramps = NULL;
3828 r_texture_numcubemaps = 0;
3830 r_loaddds = r_texture_dds_load.integer != 0;
3831 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3833 switch(vid.renderpath)
3835 case RENDERPATH_GL20:
3836 case RENDERPATH_D3D9:
3837 case RENDERPATH_D3D10:
3838 case RENDERPATH_D3D11:
3839 case RENDERPATH_SOFT:
3840 case RENDERPATH_GLES2:
3841 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3842 Cvar_SetValueQuick(&gl_combine, 1);
3843 Cvar_SetValueQuick(&r_glsl, 1);
3844 r_loadnormalmap = true;
3848 case RENDERPATH_GL13:
3849 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3850 Cvar_SetValueQuick(&gl_combine, 1);
3851 Cvar_SetValueQuick(&r_glsl, 0);
3852 r_loadnormalmap = false;
3853 r_loadgloss = false;
3856 case RENDERPATH_GL11:
3857 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3858 Cvar_SetValueQuick(&gl_combine, 0);
3859 Cvar_SetValueQuick(&r_glsl, 0);
3860 r_loadnormalmap = false;
3861 r_loadgloss = false;
3867 R_FrameData_Reset();
3871 memset(r_queries, 0, sizeof(r_queries));
3873 r_qwskincache = NULL;
3874 r_qwskincache_size = 0;
3876 // due to caching of texture_t references, the collision cache must be reset
3877 Collision_Cache_Reset(true);
3879 // set up r_skinframe loading system for textures
3880 memset(&r_skinframe, 0, sizeof(r_skinframe));
3881 r_skinframe.loadsequence = 1;
3882 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3884 r_main_texturepool = R_AllocTexturePool();
3885 R_BuildBlankTextures();
3887 if (vid.support.arb_texture_cube_map)
3890 R_BuildNormalizationCube();
3892 r_texture_fogattenuation = NULL;
3893 r_texture_fogheighttexture = NULL;
3894 r_texture_gammaramps = NULL;
3895 //r_texture_fogintensity = NULL;
3896 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3897 memset(&r_waterstate, 0, sizeof(r_waterstate));
3898 r_glsl_permutation = NULL;
3899 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3900 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3901 glslshaderstring = NULL;
3903 r_hlsl_permutation = NULL;
3904 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3905 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3907 hlslshaderstring = NULL;
3908 memset(&r_svbsp, 0, sizeof (r_svbsp));
3910 r_refdef.fogmasktable_density = 0;
3913 void gl_main_shutdown(void)
3916 R_FrameData_Reset();
3918 R_Main_FreeViewCache();
3920 switch(vid.renderpath)
3922 case RENDERPATH_GL11:
3923 case RENDERPATH_GL13:
3924 case RENDERPATH_GL20:
3925 case RENDERPATH_GLES2:
3927 qglDeleteQueriesARB(r_maxqueries, r_queries);
3929 case RENDERPATH_D3D9:
3930 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3932 case RENDERPATH_D3D10:
3933 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3935 case RENDERPATH_D3D11:
3936 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3938 case RENDERPATH_SOFT:
3944 memset(r_queries, 0, sizeof(r_queries));
3946 r_qwskincache = NULL;
3947 r_qwskincache_size = 0;
3949 // clear out the r_skinframe state
3950 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3951 memset(&r_skinframe, 0, sizeof(r_skinframe));
3954 Mem_Free(r_svbsp.nodes);
3955 memset(&r_svbsp, 0, sizeof (r_svbsp));
3956 R_FreeTexturePool(&r_main_texturepool);
3957 loadingscreentexture = NULL;
3958 r_texture_blanknormalmap = NULL;
3959 r_texture_white = NULL;
3960 r_texture_grey128 = NULL;
3961 r_texture_black = NULL;
3962 r_texture_whitecube = NULL;
3963 r_texture_normalizationcube = NULL;
3964 r_texture_fogattenuation = NULL;
3965 r_texture_fogheighttexture = NULL;
3966 r_texture_gammaramps = NULL;
3967 r_texture_numcubemaps = 0;
3968 //r_texture_fogintensity = NULL;
3969 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3970 memset(&r_waterstate, 0, sizeof(r_waterstate));
3973 r_glsl_permutation = NULL;
3974 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3975 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3976 glslshaderstring = NULL;
3978 r_hlsl_permutation = NULL;
3979 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3980 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3982 hlslshaderstring = NULL;
3985 extern void CL_ParseEntityLump(char *entitystring);
3986 void gl_main_newmap(void)
3988 // FIXME: move this code to client
3989 char *entities, entname[MAX_QPATH];
3991 Mem_Free(r_qwskincache);
3992 r_qwskincache = NULL;
3993 r_qwskincache_size = 0;
3996 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3997 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3999 CL_ParseEntityLump(entities);
4003 if (cl.worldmodel->brush.entities)
4004 CL_ParseEntityLump(cl.worldmodel->brush.entities);
4006 R_Main_FreeViewCache();
4008 R_FrameData_Reset();
4011 void GL_Main_Init(void)
4013 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4015 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4016 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4017 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4018 if (gamemode == GAME_NEHAHRA)
4020 Cvar_RegisterVariable (&gl_fogenable);
4021 Cvar_RegisterVariable (&gl_fogdensity);
4022 Cvar_RegisterVariable (&gl_fogred);
4023 Cvar_RegisterVariable (&gl_foggreen);
4024 Cvar_RegisterVariable (&gl_fogblue);
4025 Cvar_RegisterVariable (&gl_fogstart);
4026 Cvar_RegisterVariable (&gl_fogend);
4027 Cvar_RegisterVariable (&gl_skyclip);
4029 Cvar_RegisterVariable(&r_motionblur);
4030 Cvar_RegisterVariable(&r_motionblur_maxblur);
4031 Cvar_RegisterVariable(&r_motionblur_bmin);
4032 Cvar_RegisterVariable(&r_motionblur_vmin);
4033 Cvar_RegisterVariable(&r_motionblur_vmax);
4034 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4035 Cvar_RegisterVariable(&r_motionblur_randomize);
4036 Cvar_RegisterVariable(&r_damageblur);
4037 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4038 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4039 Cvar_RegisterVariable(&r_equalize_entities_by);
4040 Cvar_RegisterVariable(&r_equalize_entities_to);
4041 Cvar_RegisterVariable(&r_depthfirst);
4042 Cvar_RegisterVariable(&r_useinfinitefarclip);
4043 Cvar_RegisterVariable(&r_farclip_base);
4044 Cvar_RegisterVariable(&r_farclip_world);
4045 Cvar_RegisterVariable(&r_nearclip);
4046 Cvar_RegisterVariable(&r_showoverdraw);
4047 Cvar_RegisterVariable(&r_showbboxes);
4048 Cvar_RegisterVariable(&r_showsurfaces);
4049 Cvar_RegisterVariable(&r_showtris);
4050 Cvar_RegisterVariable(&r_shownormals);
4051 Cvar_RegisterVariable(&r_showlighting);
4052 Cvar_RegisterVariable(&r_showshadowvolumes);
4053 Cvar_RegisterVariable(&r_showcollisionbrushes);
4054 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4055 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4056 Cvar_RegisterVariable(&r_showdisabledepthtest);
4057 Cvar_RegisterVariable(&r_drawportals);
4058 Cvar_RegisterVariable(&r_drawentities);
4059 Cvar_RegisterVariable(&r_draw2d);
4060 Cvar_RegisterVariable(&r_drawworld);
4061 Cvar_RegisterVariable(&r_cullentities_trace);
4062 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4063 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4064 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4065 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4066 Cvar_RegisterVariable(&r_drawviewmodel);
4067 Cvar_RegisterVariable(&r_drawexteriormodel);
4068 Cvar_RegisterVariable(&r_speeds);
4069 Cvar_RegisterVariable(&r_fullbrights);
4070 Cvar_RegisterVariable(&r_wateralpha);
4071 Cvar_RegisterVariable(&r_dynamic);
4072 Cvar_RegisterVariable(&r_fakelight);
4073 Cvar_RegisterVariable(&r_fakelight_intensity);
4074 Cvar_RegisterVariable(&r_fullbright);
4075 Cvar_RegisterVariable(&r_shadows);
4076 Cvar_RegisterVariable(&r_shadows_darken);
4077 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4078 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4079 Cvar_RegisterVariable(&r_shadows_throwdistance);
4080 Cvar_RegisterVariable(&r_shadows_throwdirection);
4081 Cvar_RegisterVariable(&r_shadows_focus);
4082 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4083 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4084 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4085 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4086 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4087 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4088 Cvar_RegisterVariable(&r_fog_exp2);
4089 Cvar_RegisterVariable(&r_fog_clear);
4090 Cvar_RegisterVariable(&r_drawfog);
4091 Cvar_RegisterVariable(&r_transparentdepthmasking);
4092 Cvar_RegisterVariable(&r_texture_dds_load);
4093 Cvar_RegisterVariable(&r_texture_dds_save);
4094 Cvar_RegisterVariable(&r_texture_sRGB_2d);
4095 Cvar_RegisterVariable(&r_texture_sRGB_skin_diffuse);
4096 Cvar_RegisterVariable(&r_texture_sRGB_skin_gloss);
4097 Cvar_RegisterVariable(&r_texture_sRGB_skin_glow);
4098 Cvar_RegisterVariable(&r_texture_sRGB_skin_reflect);
4099 Cvar_RegisterVariable(&r_texture_sRGB_cubemap);
4100 Cvar_RegisterVariable(&r_texture_sRGB_skybox);
4101 Cvar_RegisterVariable(&r_textureunits);
4102 Cvar_RegisterVariable(&gl_combine);
4103 Cvar_RegisterVariable(&r_viewfbo);
4104 Cvar_RegisterVariable(&r_viewscale);
4105 Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4106 Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4107 Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4108 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4109 Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4110 Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4111 Cvar_RegisterVariable(&r_glsl);
4112 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4113 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4114 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4115 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4116 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4117 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4118 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4119 Cvar_RegisterVariable(&r_glsl_postprocess);
4120 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4121 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4122 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4123 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4124 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4125 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4126 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4127 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4129 Cvar_RegisterVariable(&r_water);
4130 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4131 Cvar_RegisterVariable(&r_water_clippingplanebias);
4132 Cvar_RegisterVariable(&r_water_refractdistort);
4133 Cvar_RegisterVariable(&r_water_reflectdistort);
4134 Cvar_RegisterVariable(&r_water_scissormode);
4135 Cvar_RegisterVariable(&r_lerpsprites);
4136 Cvar_RegisterVariable(&r_lerpmodels);
4137 Cvar_RegisterVariable(&r_lerplightstyles);
4138 Cvar_RegisterVariable(&r_waterscroll);
4139 Cvar_RegisterVariable(&r_bloom);
4140 Cvar_RegisterVariable(&r_bloom_colorscale);
4141 Cvar_RegisterVariable(&r_bloom_brighten);
4142 Cvar_RegisterVariable(&r_bloom_blur);
4143 Cvar_RegisterVariable(&r_bloom_resolution);
4144 Cvar_RegisterVariable(&r_bloom_colorexponent);
4145 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4146 Cvar_RegisterVariable(&r_hdr);
4147 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4148 Cvar_RegisterVariable(&r_hdr_glowintensity);
4149 Cvar_RegisterVariable(&r_hdr_range);
4150 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4151 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4152 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4153 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4154 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4155 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4156 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4157 Cvar_RegisterVariable(&developer_texturelogging);
4158 Cvar_RegisterVariable(&gl_lightmaps);
4159 Cvar_RegisterVariable(&r_test);
4160 Cvar_RegisterVariable(&r_glsl_saturation);
4161 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4162 Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4163 Cvar_RegisterVariable(&r_framedatasize);
4164 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4165 Cvar_SetValue("r_fullbrights", 0);
4166 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4168 Cvar_RegisterVariable(&r_track_sprites);
4169 Cvar_RegisterVariable(&r_track_sprites_flags);
4170 Cvar_RegisterVariable(&r_track_sprites_scalew);
4171 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4172 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4173 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4174 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4175 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4178 extern void R_Textures_Init(void);
4179 extern void GL_Draw_Init(void);
4180 extern void GL_Main_Init(void);
4181 extern void R_Shadow_Init(void);
4182 extern void R_Sky_Init(void);
4183 extern void GL_Surf_Init(void);
4184 extern void R_Particles_Init(void);
4185 extern void R_Explosion_Init(void);
4186 extern void gl_backend_init(void);
4187 extern void Sbar_Init(void);
4188 extern void R_LightningBeams_Init(void);
4189 extern void Mod_RenderInit(void);
4190 extern void Font_Init(void);
4192 void Render_Init(void)
4205 R_LightningBeams_Init();
4214 extern char *ENGINE_EXTENSIONS;
4217 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4218 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4219 gl_version = (const char *)qglGetString(GL_VERSION);
4220 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4224 if (!gl_platformextensions)
4225 gl_platformextensions = "";
4227 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4228 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4229 Con_Printf("GL_VERSION: %s\n", gl_version);
4230 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4231 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4233 VID_CheckExtensions();
4235 // LordHavoc: report supported extensions
4236 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4238 // clear to black (loading plaque will be seen over this)
4239 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4242 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4246 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4248 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4251 p = r_refdef.view.frustum + i;
4256 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4260 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4264 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4268 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4272 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4276 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4280 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4284 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4292 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4296 for (i = 0;i < numplanes;i++)
4303 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4307 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4311 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4315 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4319 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4323 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4327 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4331 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4339 //==================================================================================
4341 // LordHavoc: this stores temporary data used within the same frame
4343 typedef struct r_framedata_mem_s
4345 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4346 size_t size; // how much usable space
4347 size_t current; // how much space in use
4348 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4349 size_t wantedsize; // how much space was allocated
4350 unsigned char *data; // start of real data (16byte aligned)
4354 static r_framedata_mem_t *r_framedata_mem;
4356 void R_FrameData_Reset(void)
4358 while (r_framedata_mem)
4360 r_framedata_mem_t *next = r_framedata_mem->purge;
4361 Mem_Free(r_framedata_mem);
4362 r_framedata_mem = next;
4366 void R_FrameData_Resize(void)
4369 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4370 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4371 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4373 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4374 newmem->wantedsize = wantedsize;
4375 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4376 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4377 newmem->current = 0;
4379 newmem->purge = r_framedata_mem;
4380 r_framedata_mem = newmem;
4384 void R_FrameData_NewFrame(void)
4386 R_FrameData_Resize();
4387 if (!r_framedata_mem)
4389 // if we ran out of space on the last frame, free the old memory now
4390 while (r_framedata_mem->purge)
4392 // repeatedly remove the second item in the list, leaving only head
4393 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4394 Mem_Free(r_framedata_mem->purge);
4395 r_framedata_mem->purge = next;
4397 // reset the current mem pointer
4398 r_framedata_mem->current = 0;
4399 r_framedata_mem->mark = 0;
4402 void *R_FrameData_Alloc(size_t size)
4406 // align to 16 byte boundary - the data pointer is already aligned, so we
4407 // only need to ensure the size of every allocation is also aligned
4408 size = (size + 15) & ~15;
4410 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4412 // emergency - we ran out of space, allocate more memory
4413 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4414 R_FrameData_Resize();
4417 data = r_framedata_mem->data + r_framedata_mem->current;
4418 r_framedata_mem->current += size;
4420 // count the usage for stats
4421 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4422 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4424 return (void *)data;
4427 void *R_FrameData_Store(size_t size, void *data)
4429 void *d = R_FrameData_Alloc(size);
4431 memcpy(d, data, size);
4435 void R_FrameData_SetMark(void)
4437 if (!r_framedata_mem)
4439 r_framedata_mem->mark = r_framedata_mem->current;
4442 void R_FrameData_ReturnToMark(void)
4444 if (!r_framedata_mem)
4446 r_framedata_mem->current = r_framedata_mem->mark;
4449 //==================================================================================
4451 // LordHavoc: animcache originally written by Echon, rewritten since then
4454 * Animation cache prevents re-generating mesh data for an animated model
4455 * multiple times in one frame for lighting, shadowing, reflections, etc.
4458 void R_AnimCache_Free(void)
4462 void R_AnimCache_ClearCache(void)
4465 entity_render_t *ent;
4467 for (i = 0;i < r_refdef.scene.numentities;i++)
4469 ent = r_refdef.scene.entities[i];
4470 ent->animcache_vertex3f = NULL;
4471 ent->animcache_normal3f = NULL;
4472 ent->animcache_svector3f = NULL;
4473 ent->animcache_tvector3f = NULL;
4474 ent->animcache_vertexmesh = NULL;
4475 ent->animcache_vertex3fbuffer = NULL;
4476 ent->animcache_vertexmeshbuffer = NULL;
4480 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4484 // check if we need the meshbuffers
4485 if (!vid.useinterleavedarrays)
4488 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4489 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4490 // TODO: upload vertex3f buffer?
4491 if (ent->animcache_vertexmesh)
4493 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4494 for (i = 0;i < numvertices;i++)
4495 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4496 if (ent->animcache_svector3f)
4497 for (i = 0;i < numvertices;i++)
4498 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4499 if (ent->animcache_tvector3f)
4500 for (i = 0;i < numvertices;i++)
4501 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4502 if (ent->animcache_normal3f)
4503 for (i = 0;i < numvertices;i++)
4504 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4505 // TODO: upload vertexmeshbuffer?
4509 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4511 dp_model_t *model = ent->model;
4513 // see if it's already cached this frame
4514 if (ent->animcache_vertex3f)
4516 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4517 if (wantnormals || wanttangents)
4519 if (ent->animcache_normal3f)
4520 wantnormals = false;
4521 if (ent->animcache_svector3f)
4522 wanttangents = false;
4523 if (wantnormals || wanttangents)
4525 numvertices = model->surfmesh.num_vertices;
4527 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4530 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4531 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4533 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4534 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4540 // see if this ent is worth caching
4541 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4543 // get some memory for this entity and generate mesh data
4544 numvertices = model->surfmesh.num_vertices;
4545 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4547 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4550 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4551 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4553 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4554 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4559 void R_AnimCache_CacheVisibleEntities(void)
4562 qboolean wantnormals = true;
4563 qboolean wanttangents = !r_showsurfaces.integer;
4565 switch(vid.renderpath)
4567 case RENDERPATH_GL20:
4568 case RENDERPATH_D3D9:
4569 case RENDERPATH_D3D10:
4570 case RENDERPATH_D3D11:
4571 case RENDERPATH_GLES2:
4573 case RENDERPATH_GL13:
4574 case RENDERPATH_GL11:
4575 wanttangents = false;
4577 case RENDERPATH_SOFT:
4581 if (r_shownormals.integer)
4582 wanttangents = wantnormals = true;
4584 // TODO: thread this
4585 // NOTE: R_PrepareRTLights() also caches entities
4587 for (i = 0;i < r_refdef.scene.numentities;i++)
4588 if (r_refdef.viewcache.entityvisible[i])
4589 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4592 //==================================================================================
4594 static void R_View_UpdateEntityLighting (void)
4597 entity_render_t *ent;
4598 vec3_t tempdiffusenormal, avg;
4599 vec_t f, fa, fd, fdd;
4600 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4602 for (i = 0;i < r_refdef.scene.numentities;i++)
4604 ent = r_refdef.scene.entities[i];
4606 // skip unseen models
4607 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4611 if (ent->model && ent->model->brush.num_leafs)
4613 // TODO: use modellight for r_ambient settings on world?
4614 VectorSet(ent->modellight_ambient, 0, 0, 0);
4615 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4616 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4620 // fetch the lighting from the worldmodel data
4621 VectorClear(ent->modellight_ambient);
4622 VectorClear(ent->modellight_diffuse);
4623 VectorClear(tempdiffusenormal);
4624 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4627 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4629 // complete lightning for lit sprites
4630 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4631 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4633 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4634 org[2] = org[2] + r_overheadsprites_pushback.value;
4635 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4638 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4640 if(ent->flags & RENDER_EQUALIZE)
4642 // first fix up ambient lighting...
4643 if(r_equalize_entities_minambient.value > 0)
4645 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4648 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4649 if(fa < r_equalize_entities_minambient.value * fd)
4652 // fa'/fd' = minambient
4653 // fa'+0.25*fd' = fa+0.25*fd
4655 // fa' = fd' * minambient
4656 // fd'*(0.25+minambient) = fa+0.25*fd
4658 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4659 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4661 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4662 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
4663 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4664 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4669 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4671 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4672 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4676 // adjust brightness and saturation to target
4677 avg[0] = avg[1] = avg[2] = fa / f;
4678 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4679 avg[0] = avg[1] = avg[2] = fd / f;
4680 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4686 VectorSet(ent->modellight_ambient, 1, 1, 1);
4688 // move the light direction into modelspace coordinates for lighting code
4689 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4690 if(VectorLength2(ent->modellight_lightdir) == 0)
4691 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4692 VectorNormalize(ent->modellight_lightdir);
4696 #define MAX_LINEOFSIGHTTRACES 64
4698 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4701 vec3_t boxmins, boxmaxs;
4704 dp_model_t *model = r_refdef.scene.worldmodel;
4706 if (!model || !model->brush.TraceLineOfSight)
4709 // expand the box a little
4710 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4711 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4712 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4713 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4714 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4715 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4717 // return true if eye is inside enlarged box
4718 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4722 VectorCopy(eye, start);
4723 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4724 if (model->brush.TraceLineOfSight(model, start, end))
4727 // try various random positions
4728 for (i = 0;i < numsamples;i++)
4730 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4731 if (model->brush.TraceLineOfSight(model, start, end))
4739 static void R_View_UpdateEntityVisible (void)
4744 entity_render_t *ent;
4746 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4747 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4748 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4749 : RENDER_EXTERIORMODEL;
4750 if (!r_drawviewmodel.integer)
4751 renderimask |= RENDER_VIEWMODEL;
4752 if (!r_drawexteriormodel.integer)
4753 renderimask |= RENDER_EXTERIORMODEL;
4754 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4756 // worldmodel can check visibility
4757 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4758 for (i = 0;i < r_refdef.scene.numentities;i++)
4760 ent = r_refdef.scene.entities[i];
4761 if (!(ent->flags & renderimask))
4762 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)))
4763 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))
4764 r_refdef.viewcache.entityvisible[i] = true;
4769 // no worldmodel or it can't check visibility
4770 for (i = 0;i < r_refdef.scene.numentities;i++)
4772 ent = r_refdef.scene.entities[i];
4773 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));
4776 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4777 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4779 for (i = 0;i < r_refdef.scene.numentities;i++)
4781 if (!r_refdef.viewcache.entityvisible[i])
4783 ent = r_refdef.scene.entities[i];
4784 if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4786 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4788 continue; // temp entities do pvs only
4789 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4790 ent->last_trace_visibility = realtime;
4791 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4792 r_refdef.viewcache.entityvisible[i] = 0;
4798 /// only used if skyrendermasked, and normally returns false
4799 int R_DrawBrushModelsSky (void)
4802 entity_render_t *ent;
4805 for (i = 0;i < r_refdef.scene.numentities;i++)
4807 if (!r_refdef.viewcache.entityvisible[i])
4809 ent = r_refdef.scene.entities[i];
4810 if (!ent->model || !ent->model->DrawSky)
4812 ent->model->DrawSky(ent);
4818 static void R_DrawNoModel(entity_render_t *ent);
4819 static void R_DrawModels(void)
4822 entity_render_t *ent;
4824 for (i = 0;i < r_refdef.scene.numentities;i++)
4826 if (!r_refdef.viewcache.entityvisible[i])
4828 ent = r_refdef.scene.entities[i];
4829 r_refdef.stats.entities++;
4830 if (ent->model && ent->model->Draw != NULL)
4831 ent->model->Draw(ent);
4837 static void R_DrawModelsDepth(void)
4840 entity_render_t *ent;
4842 for (i = 0;i < r_refdef.scene.numentities;i++)
4844 if (!r_refdef.viewcache.entityvisible[i])
4846 ent = r_refdef.scene.entities[i];
4847 if (ent->model && ent->model->DrawDepth != NULL)
4848 ent->model->DrawDepth(ent);
4852 static void R_DrawModelsDebug(void)
4855 entity_render_t *ent;
4857 for (i = 0;i < r_refdef.scene.numentities;i++)
4859 if (!r_refdef.viewcache.entityvisible[i])
4861 ent = r_refdef.scene.entities[i];
4862 if (ent->model && ent->model->DrawDebug != NULL)
4863 ent->model->DrawDebug(ent);
4867 static void R_DrawModelsAddWaterPlanes(void)
4870 entity_render_t *ent;
4872 for (i = 0;i < r_refdef.scene.numentities;i++)
4874 if (!r_refdef.viewcache.entityvisible[i])
4876 ent = r_refdef.scene.entities[i];
4877 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4878 ent->model->DrawAddWaterPlanes(ent);
4882 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4884 if (r_hdr_irisadaptation.integer)
4888 vec3_t diffusenormal;
4893 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4894 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4895 brightness = max(0.0000001f, brightness);
4896 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4897 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4898 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4899 current = r_hdr_irisadaptation_value.value;
4901 current = min(current + adjust, goal);
4902 else if (current > goal)
4903 current = max(current - adjust, goal);
4904 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4905 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4907 else if (r_hdr_irisadaptation_value.value != 1.0f)
4908 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4911 static void R_View_SetFrustum(const int *scissor)
4914 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4915 vec3_t forward, left, up, origin, v;
4919 // flipped x coordinates (because x points left here)
4920 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4921 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4923 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4924 switch(vid.renderpath)
4926 case RENDERPATH_D3D9:
4927 case RENDERPATH_D3D10:
4928 case RENDERPATH_D3D11:
4929 // non-flipped y coordinates
4930 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4931 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4933 case RENDERPATH_SOFT:
4934 case RENDERPATH_GL11:
4935 case RENDERPATH_GL13:
4936 case RENDERPATH_GL20:
4937 case RENDERPATH_GLES2:
4938 // non-flipped y coordinates
4939 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4940 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4945 // we can't trust r_refdef.view.forward and friends in reflected scenes
4946 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4949 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4950 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4951 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4952 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4953 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4954 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4955 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4956 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4957 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4958 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4959 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4960 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4964 zNear = r_refdef.nearclip;
4965 nudge = 1.0 - 1.0 / (1<<23);
4966 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4967 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4968 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4969 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4970 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4971 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4972 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4973 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4979 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4980 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4981 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4982 r_refdef.view.frustum[0].dist = m[15] - m[12];
4984 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4985 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4986 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4987 r_refdef.view.frustum[1].dist = m[15] + m[12];
4989 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4990 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4991 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4992 r_refdef.view.frustum[2].dist = m[15] - m[13];
4994 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4995 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4996 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4997 r_refdef.view.frustum[3].dist = m[15] + m[13];
4999 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5000 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5001 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5002 r_refdef.view.frustum[4].dist = m[15] - m[14];
5004 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5005 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5006 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5007 r_refdef.view.frustum[5].dist = m[15] + m[14];
5010 if (r_refdef.view.useperspective)
5012 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5013 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]);
5014 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]);
5015 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]);
5016 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]);
5018 // then the normals from the corners relative to origin
5019 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5020 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5021 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5022 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5024 // in a NORMAL view, forward cross left == up
5025 // in a REFLECTED view, forward cross left == down
5026 // so our cross products above need to be adjusted for a left handed coordinate system
5027 CrossProduct(forward, left, v);
5028 if(DotProduct(v, up) < 0)
5030 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5031 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5032 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5033 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5036 // Leaving those out was a mistake, those were in the old code, and they
5037 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5038 // I couldn't reproduce it after adding those normalizations. --blub
5039 VectorNormalize(r_refdef.view.frustum[0].normal);
5040 VectorNormalize(r_refdef.view.frustum[1].normal);
5041 VectorNormalize(r_refdef.view.frustum[2].normal);
5042 VectorNormalize(r_refdef.view.frustum[3].normal);
5044 // make the corners absolute
5045 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5046 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5047 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5048 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5051 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5053 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5054 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5055 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5056 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5057 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5061 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5062 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5063 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5064 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5065 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5066 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5067 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5068 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5069 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5070 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5072 r_refdef.view.numfrustumplanes = 5;
5074 if (r_refdef.view.useclipplane)
5076 r_refdef.view.numfrustumplanes = 6;
5077 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5080 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5081 PlaneClassify(r_refdef.view.frustum + i);
5083 // LordHavoc: note to all quake engine coders, Quake had a special case
5084 // for 90 degrees which assumed a square view (wrong), so I removed it,
5085 // Quake2 has it disabled as well.
5087 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5088 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5089 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5090 //PlaneClassify(&frustum[0]);
5092 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5093 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5094 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5095 //PlaneClassify(&frustum[1]);
5097 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5098 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5099 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5100 //PlaneClassify(&frustum[2]);
5102 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5103 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5104 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5105 //PlaneClassify(&frustum[3]);
5108 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5109 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5110 //PlaneClassify(&frustum[4]);
5113 void R_View_UpdateWithScissor(const int *myscissor)
5115 R_Main_ResizeViewCache();
5116 R_View_SetFrustum(myscissor);
5117 R_View_WorldVisibility(r_refdef.view.useclipplane);
5118 R_View_UpdateEntityVisible();
5119 R_View_UpdateEntityLighting();
5122 void R_View_Update(void)
5124 R_Main_ResizeViewCache();
5125 R_View_SetFrustum(NULL);
5126 R_View_WorldVisibility(r_refdef.view.useclipplane);
5127 R_View_UpdateEntityVisible();
5128 R_View_UpdateEntityLighting();
5131 float viewscalefpsadjusted = 1.0f;
5133 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5135 float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5136 scale = bound(0.03125f, scale, 1.0f);
5137 *outwidth = (int)ceil(width * scale);
5138 *outheight = (int)ceil(height * scale);
5141 void R_Mesh_SetMainRenderTargets(void)
5143 if (r_bloomstate.fbo_framebuffer)
5144 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5146 R_Mesh_ResetRenderTargets();
5149 void R_SetupView(qboolean allowwaterclippingplane)
5151 const float *customclipplane = NULL;
5153 int scaledwidth, scaledheight;
5154 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5156 // LordHavoc: couldn't figure out how to make this approach the
5157 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5158 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5159 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5160 dist = r_refdef.view.clipplane.dist;
5161 plane[0] = r_refdef.view.clipplane.normal[0];
5162 plane[1] = r_refdef.view.clipplane.normal[1];
5163 plane[2] = r_refdef.view.clipplane.normal[2];
5165 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5168 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5169 if (!r_refdef.view.useperspective)
5170 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);
5171 else if (vid.stencil && r_useinfinitefarclip.integer)
5172 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);
5174 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);
5175 R_Mesh_SetMainRenderTargets();
5176 R_SetViewport(&r_refdef.view.viewport);
5177 if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5179 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5180 float screenplane[4];
5181 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5182 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5183 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5184 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5185 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5189 void R_EntityMatrix(const matrix4x4_t *matrix)
5191 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5193 gl_modelmatrixchanged = false;
5194 gl_modelmatrix = *matrix;
5195 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5196 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5197 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5198 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5200 switch(vid.renderpath)
5202 case RENDERPATH_D3D9:
5204 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5205 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5208 case RENDERPATH_D3D10:
5209 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5211 case RENDERPATH_D3D11:
5212 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5214 case RENDERPATH_GL13:
5215 case RENDERPATH_GL11:
5216 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5218 case RENDERPATH_SOFT:
5219 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5220 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5222 case RENDERPATH_GL20:
5223 case RENDERPATH_GLES2:
5224 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5225 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5231 void R_ResetViewRendering2D(void)
5233 r_viewport_t viewport;
5236 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5237 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);
5238 R_Mesh_ResetRenderTargets();
5239 R_SetViewport(&viewport);
5240 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5241 GL_Color(1, 1, 1, 1);
5242 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5243 GL_BlendFunc(GL_ONE, GL_ZERO);
5244 GL_ScissorTest(false);
5245 GL_DepthMask(false);
5246 GL_DepthRange(0, 1);
5247 GL_DepthTest(false);
5248 GL_DepthFunc(GL_LEQUAL);
5249 R_EntityMatrix(&identitymatrix);
5250 R_Mesh_ResetTextureState();
5251 GL_PolygonOffset(0, 0);
5252 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5253 switch(vid.renderpath)
5255 case RENDERPATH_GL11:
5256 case RENDERPATH_GL13:
5257 case RENDERPATH_GL20:
5258 case RENDERPATH_GLES2:
5259 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5261 case RENDERPATH_D3D9:
5262 case RENDERPATH_D3D10:
5263 case RENDERPATH_D3D11:
5264 case RENDERPATH_SOFT:
5267 GL_CullFace(GL_NONE);
5270 void R_ResetViewRendering3D(void)
5275 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5276 GL_Color(1, 1, 1, 1);
5277 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5278 GL_BlendFunc(GL_ONE, GL_ZERO);
5279 GL_ScissorTest(true);
5281 GL_DepthRange(0, 1);
5283 GL_DepthFunc(GL_LEQUAL);
5284 R_EntityMatrix(&identitymatrix);
5285 R_Mesh_ResetTextureState();
5286 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5287 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5288 switch(vid.renderpath)
5290 case RENDERPATH_GL11:
5291 case RENDERPATH_GL13:
5292 case RENDERPATH_GL20:
5293 case RENDERPATH_GLES2:
5294 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5296 case RENDERPATH_D3D9:
5297 case RENDERPATH_D3D10:
5298 case RENDERPATH_D3D11:
5299 case RENDERPATH_SOFT:
5302 GL_CullFace(r_refdef.view.cullface_back);
5307 R_RenderView_UpdateViewVectors
5310 static void R_RenderView_UpdateViewVectors(void)
5312 // break apart the view matrix into vectors for various purposes
5313 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5314 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5315 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5316 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5317 // make an inverted copy of the view matrix for tracking sprites
5318 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5321 void R_RenderScene(void);
5322 void R_RenderWaterPlanes(void);
5324 static void R_Water_StartFrame(void)
5327 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5328 r_waterstate_waterplane_t *p;
5330 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5333 switch(vid.renderpath)
5335 case RENDERPATH_GL20:
5336 case RENDERPATH_D3D9:
5337 case RENDERPATH_D3D10:
5338 case RENDERPATH_D3D11:
5339 case RENDERPATH_SOFT:
5340 case RENDERPATH_GLES2:
5342 case RENDERPATH_GL13:
5343 case RENDERPATH_GL11:
5347 // set waterwidth and waterheight to the water resolution that will be
5348 // used (often less than the screen resolution for faster rendering)
5349 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5350 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5352 // calculate desired texture sizes
5353 // can't use water if the card does not support the texture size
5354 if (!r_water.integer || r_showsurfaces.integer)
5355 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5356 else if (vid.support.arb_texture_non_power_of_two)
5358 texturewidth = waterwidth;
5359 textureheight = waterheight;
5360 camerawidth = waterwidth;
5361 cameraheight = waterheight;
5365 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5366 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5367 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5368 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5371 // allocate textures as needed
5372 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5374 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5375 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5377 if (p->texture_refraction)
5378 R_FreeTexture(p->texture_refraction);
5379 p->texture_refraction = NULL;
5380 if (p->texture_reflection)
5381 R_FreeTexture(p->texture_reflection);
5382 p->texture_reflection = NULL;
5383 if (p->texture_camera)
5384 R_FreeTexture(p->texture_camera);
5385 p->texture_camera = NULL;
5387 memset(&r_waterstate, 0, sizeof(r_waterstate));
5388 r_waterstate.texturewidth = texturewidth;
5389 r_waterstate.textureheight = textureheight;
5390 r_waterstate.camerawidth = camerawidth;
5391 r_waterstate.cameraheight = cameraheight;
5394 if (r_waterstate.texturewidth)
5396 r_waterstate.enabled = true;
5398 // when doing a reduced render (HDR) we want to use a smaller area
5399 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5400 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5402 // set up variables that will be used in shader setup
5403 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5404 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5405 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5406 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5409 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5410 r_waterstate.numwaterplanes = 0;
5413 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5415 int triangleindex, planeindex;
5421 r_waterstate_waterplane_t *p;
5422 texture_t *t = R_GetCurrentTexture(surface->texture);
5424 // just use the first triangle with a valid normal for any decisions
5425 VectorClear(normal);
5426 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5428 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5429 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5430 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5431 TriangleNormal(vert[0], vert[1], vert[2], normal);
5432 if (VectorLength2(normal) >= 0.001)
5436 VectorCopy(normal, plane.normal);
5437 VectorNormalize(plane.normal);
5438 plane.dist = DotProduct(vert[0], plane.normal);
5439 PlaneClassify(&plane);
5440 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5442 // skip backfaces (except if nocullface is set)
5443 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5445 VectorNegate(plane.normal, plane.normal);
5447 PlaneClassify(&plane);
5451 // find a matching plane if there is one
5452 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5453 if(p->camera_entity == t->camera_entity)
5454 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5456 if (planeindex >= r_waterstate.maxwaterplanes)
5457 return; // nothing we can do, out of planes
5459 // if this triangle does not fit any known plane rendered this frame, add one
5460 if (planeindex >= r_waterstate.numwaterplanes)
5462 // store the new plane
5463 r_waterstate.numwaterplanes++;
5465 // clear materialflags and pvs
5466 p->materialflags = 0;
5467 p->pvsvalid = false;
5468 p->camera_entity = t->camera_entity;
5469 VectorCopy(surface->mins, p->mins);
5470 VectorCopy(surface->maxs, p->maxs);
5475 p->mins[0] = min(p->mins[0], surface->mins[0]);
5476 p->mins[1] = min(p->mins[1], surface->mins[1]);
5477 p->mins[2] = min(p->mins[2], surface->mins[2]);
5478 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5479 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5480 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5482 // merge this surface's materialflags into the waterplane
5483 p->materialflags |= t->currentmaterialflags;
5484 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5486 // merge this surface's PVS into the waterplane
5487 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5488 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5489 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5491 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5497 static void R_Water_ProcessPlanes(void)
5500 r_refdef_view_t originalview;
5501 r_refdef_view_t myview;
5503 r_waterstate_waterplane_t *p;
5506 originalview = r_refdef.view;
5508 // make sure enough textures are allocated
5509 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5511 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5513 if (!p->texture_refraction)
5514 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);
5515 if (!p->texture_refraction)
5518 else if (p->materialflags & MATERIALFLAG_CAMERA)
5520 if (!p->texture_camera)
5521 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);
5522 if (!p->texture_camera)
5526 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5528 if (!p->texture_reflection)
5529 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);
5530 if (!p->texture_reflection)
5536 r_refdef.view = originalview;
5537 r_refdef.view.showdebug = false;
5538 r_refdef.view.width = r_waterstate.waterwidth;
5539 r_refdef.view.height = r_waterstate.waterheight;
5540 r_refdef.view.useclipplane = true;
5541 myview = r_refdef.view;
5542 r_waterstate.renderingscene = true;
5543 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5545 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5547 r_refdef.view = myview;
5548 if(r_water_scissormode.integer)
5551 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5552 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5555 // render reflected scene and copy into texture
5556 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5557 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5558 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5559 r_refdef.view.clipplane = p->plane;
5561 // reverse the cullface settings for this render
5562 r_refdef.view.cullface_front = GL_FRONT;
5563 r_refdef.view.cullface_back = GL_BACK;
5564 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5566 r_refdef.view.usecustompvs = true;
5568 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5570 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5573 R_ResetViewRendering3D();
5574 R_ClearScreen(r_refdef.fogenabled);
5575 if(r_water_scissormode.integer & 2)
5576 R_View_UpdateWithScissor(myscissor);
5579 if(r_water_scissormode.integer & 1)
5580 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5583 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);
5586 // render the normal view scene and copy into texture
5587 // (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)
5588 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5590 r_refdef.view = myview;
5591 if(r_water_scissormode.integer)
5594 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5595 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5598 r_waterstate.renderingrefraction = true;
5600 r_refdef.view.clipplane = p->plane;
5601 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5602 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5604 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5606 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5607 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5608 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5609 R_RenderView_UpdateViewVectors();
5610 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5612 r_refdef.view.usecustompvs = true;
5613 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);
5617 PlaneClassify(&r_refdef.view.clipplane);
5619 R_ResetViewRendering3D();
5620 R_ClearScreen(r_refdef.fogenabled);
5621 if(r_water_scissormode.integer & 2)
5622 R_View_UpdateWithScissor(myscissor);
5625 if(r_water_scissormode.integer & 1)
5626 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5629 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);
5630 r_waterstate.renderingrefraction = false;
5632 else if (p->materialflags & MATERIALFLAG_CAMERA)
5634 r_refdef.view = myview;
5636 r_refdef.view.clipplane = p->plane;
5637 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5638 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5640 r_refdef.view.width = r_waterstate.camerawidth;
5641 r_refdef.view.height = r_waterstate.cameraheight;
5642 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5643 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5645 if(p->camera_entity)
5647 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5648 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5651 // note: all of the view is used for displaying... so
5652 // there is no use in scissoring
5654 // reverse the cullface settings for this render
5655 r_refdef.view.cullface_front = GL_FRONT;
5656 r_refdef.view.cullface_back = GL_BACK;
5657 // also reverse the view matrix
5658 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
5659 R_RenderView_UpdateViewVectors();
5660 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5662 r_refdef.view.usecustompvs = true;
5663 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);
5666 // camera needs no clipplane
5667 r_refdef.view.useclipplane = false;
5669 PlaneClassify(&r_refdef.view.clipplane);
5671 R_ResetViewRendering3D();
5672 R_ClearScreen(r_refdef.fogenabled);
5676 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);
5677 r_waterstate.renderingrefraction = false;
5681 if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5682 r_waterstate.renderingscene = false;
5683 r_refdef.view = originalview;
5684 R_ResetViewRendering3D();
5685 R_ClearScreen(r_refdef.fogenabled);
5689 r_refdef.view = originalview;
5690 r_waterstate.renderingscene = false;
5691 Cvar_SetValueQuick(&r_water, 0);
5692 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5696 void R_Bloom_StartFrame(void)
5698 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5699 int viewwidth, viewheight;
5702 if (r_viewscale_fpsscaling.integer)
5704 double actualframetime;
5705 double targetframetime;
5707 actualframetime = r_refdef.lastdrawscreentime;
5708 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5709 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5710 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5711 if (r_viewscale_fpsscaling_stepsize.value > 0)
5712 adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5713 viewscalefpsadjusted += adjust;
5714 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5717 viewscalefpsadjusted = 1.0f;
5719 R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5721 switch(vid.renderpath)
5723 case RENDERPATH_GL20:
5724 case RENDERPATH_D3D9:
5725 case RENDERPATH_D3D10:
5726 case RENDERPATH_D3D11:
5727 case RENDERPATH_SOFT:
5728 case RENDERPATH_GLES2:
5730 case RENDERPATH_GL13:
5731 case RENDERPATH_GL11:
5735 // set bloomwidth and bloomheight to the bloom resolution that will be
5736 // used (often less than the screen resolution for faster rendering)
5737 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5738 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5739 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5740 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5741 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5743 // calculate desired texture sizes
5744 if (vid.support.arb_texture_non_power_of_two)
5746 screentexturewidth = vid.width;
5747 screentextureheight = vid.height;
5748 bloomtexturewidth = r_bloomstate.bloomwidth;
5749 bloomtextureheight = r_bloomstate.bloomheight;
5753 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5754 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5755 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5756 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5759 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))
5761 Cvar_SetValueQuick(&r_hdr, 0);
5762 Cvar_SetValueQuick(&r_bloom, 0);
5763 Cvar_SetValueQuick(&r_motionblur, 0);
5764 Cvar_SetValueQuick(&r_damageblur, 0);
5767 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)
5768 screentexturewidth = screentextureheight = 0;
5769 if (!r_hdr.integer && !r_bloom.integer)
5770 bloomtexturewidth = bloomtextureheight = 0;
5772 textype = TEXTYPE_COLORBUFFER;
5773 switch (vid.renderpath)
5775 case RENDERPATH_GL20:
5776 case RENDERPATH_GLES2:
5777 if (vid.support.ext_framebuffer_object)
5779 if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5780 if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5783 case RENDERPATH_D3D9:
5784 case RENDERPATH_D3D10:
5785 case RENDERPATH_D3D11:
5786 case RENDERPATH_SOFT:
5787 case RENDERPATH_GL13:
5788 case RENDERPATH_GL11:
5792 // allocate textures as needed
5793 if (r_bloomstate.screentexturewidth != screentexturewidth
5794 || r_bloomstate.screentextureheight != screentextureheight
5795 || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5796 || r_bloomstate.bloomtextureheight != bloomtextureheight
5797 || r_bloomstate.texturetype != textype
5798 || r_bloomstate.viewfbo != r_viewfbo.integer)
5800 if (r_bloomstate.texture_bloom)
5801 R_FreeTexture(r_bloomstate.texture_bloom);
5802 r_bloomstate.texture_bloom = NULL;
5803 if (r_bloomstate.texture_screen)
5804 R_FreeTexture(r_bloomstate.texture_screen);
5805 r_bloomstate.texture_screen = NULL;
5806 if (r_bloomstate.fbo_framebuffer)
5807 R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5808 r_bloomstate.fbo_framebuffer = 0;
5809 if (r_bloomstate.texture_framebuffercolor)
5810 R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5811 r_bloomstate.texture_framebuffercolor = NULL;
5812 if (r_bloomstate.texture_framebufferdepth)
5813 R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5814 r_bloomstate.texture_framebufferdepth = NULL;
5815 r_bloomstate.screentexturewidth = screentexturewidth;
5816 r_bloomstate.screentextureheight = screentextureheight;
5817 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5818 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);
5819 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5821 // FIXME: choose depth bits based on a cvar
5822 r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5823 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);
5824 r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5825 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5826 // render depth into one texture and normalmap into the other
5830 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5831 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
5832 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
5833 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
5834 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
5837 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5838 r_bloomstate.bloomtextureheight = bloomtextureheight;
5839 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5840 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);
5841 r_bloomstate.viewfbo = r_viewfbo.integer;
5842 r_bloomstate.texturetype = textype;
5845 // when doing a reduced render (HDR) we want to use a smaller area
5846 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5847 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5848 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5849 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5850 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5852 // set up a texcoord array for the full resolution screen image
5853 // (we have to keep this around to copy back during final render)
5854 r_bloomstate.screentexcoord2f[0] = 0;
5855 r_bloomstate.screentexcoord2f[1] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5856 r_bloomstate.screentexcoord2f[2] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5857 r_bloomstate.screentexcoord2f[3] = (float)viewheight / (float)r_bloomstate.screentextureheight;
5858 r_bloomstate.screentexcoord2f[4] = (float)viewwidth / (float)r_bloomstate.screentexturewidth;
5859 r_bloomstate.screentexcoord2f[5] = 0;
5860 r_bloomstate.screentexcoord2f[6] = 0;
5861 r_bloomstate.screentexcoord2f[7] = 0;
5863 // set up a texcoord array for the reduced resolution bloom image
5864 // (which will be additive blended over the screen image)
5865 r_bloomstate.bloomtexcoord2f[0] = 0;
5866 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5867 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5868 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5869 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5870 r_bloomstate.bloomtexcoord2f[5] = 0;
5871 r_bloomstate.bloomtexcoord2f[6] = 0;
5872 r_bloomstate.bloomtexcoord2f[7] = 0;
5874 switch(vid.renderpath)
5876 case RENDERPATH_GL11:
5877 case RENDERPATH_GL13:
5878 case RENDERPATH_GL20:
5879 case RENDERPATH_SOFT:
5880 case RENDERPATH_GLES2:
5882 case RENDERPATH_D3D9:
5883 case RENDERPATH_D3D10:
5884 case RENDERPATH_D3D11:
5887 for (i = 0;i < 4;i++)
5889 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5890 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5891 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5892 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5898 if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
5900 r_bloomstate.enabled = true;
5901 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
5904 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);
5906 if (r_bloomstate.fbo_framebuffer)
5907 r_refdef.view.clear = true;
5910 void R_Bloom_CopyBloomTexture(float colorscale)
5912 r_refdef.stats.bloom++;
5914 // scale down screen texture to the bloom texture size
5916 R_Mesh_SetMainRenderTargets();
5917 R_SetViewport(&r_bloomstate.viewport);
5918 GL_BlendFunc(GL_ONE, GL_ZERO);
5919 GL_Color(colorscale, colorscale, colorscale, 1);
5920 // 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...
5921 switch(vid.renderpath)
5923 case RENDERPATH_GL11:
5924 case RENDERPATH_GL13:
5925 case RENDERPATH_GL20:
5926 case RENDERPATH_SOFT:
5927 case RENDERPATH_GLES2:
5928 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5930 case RENDERPATH_D3D9:
5931 case RENDERPATH_D3D10:
5932 case RENDERPATH_D3D11:
5933 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5936 // TODO: do boxfilter scale-down in shader?
5937 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5938 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5939 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5941 // we now have a bloom image in the framebuffer
5942 // copy it into the bloom image texture for later processing
5943 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);
5944 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5947 void R_Bloom_CopyHDRTexture(void)
5949 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);
5950 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5953 void R_Bloom_MakeTexture(void)
5956 float xoffset, yoffset, r, brighten;
5958 r_refdef.stats.bloom++;
5960 R_ResetViewRendering2D();
5962 // we have a bloom image in the framebuffer
5964 R_SetViewport(&r_bloomstate.viewport);
5966 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5969 r = bound(0, r_bloom_colorexponent.value / x, 1);
5970 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5972 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5973 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5974 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5975 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5977 // copy the vertically blurred bloom view to a texture
5978 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);
5979 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5982 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5983 brighten = r_bloom_brighten.value;
5984 if (r_bloomstate.hdr)
5985 brighten *= r_hdr_range.value;
5986 brighten = sqrt(brighten);
5988 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5989 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5991 for (dir = 0;dir < 2;dir++)
5993 // blend on at multiple vertical offsets to achieve a vertical blur
5994 // TODO: do offset blends using GLSL
5995 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5996 GL_BlendFunc(GL_ONE, GL_ZERO);
5997 for (x = -range;x <= range;x++)
5999 if (!dir){xoffset = 0;yoffset = x;}
6000 else {xoffset = x;yoffset = 0;}
6001 xoffset /= (float)r_bloomstate.bloomtexturewidth;
6002 yoffset /= (float)r_bloomstate.bloomtextureheight;
6003 // compute a texcoord array with the specified x and y offset
6004 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6005 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6006 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6007 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6008 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6009 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6010 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6011 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6012 // this r value looks like a 'dot' particle, fading sharply to
6013 // black at the edges
6014 // (probably not realistic but looks good enough)
6015 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6016 //r = brighten/(range*2+1);
6017 r = brighten / (range * 2 + 1);
6019 r *= (1 - x*x/(float)(range*range));
6020 GL_Color(r, r, r, 1);
6021 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6022 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6023 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6024 GL_BlendFunc(GL_ONE, GL_ONE);
6027 // copy the vertically blurred bloom view to a texture
6028 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);
6029 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6033 void R_HDR_RenderBloomTexture(void)
6035 int oldwidth, oldheight;
6036 float oldcolorscale;
6037 qboolean oldwaterstate;
6039 oldwaterstate = r_waterstate.enabled;
6040 oldcolorscale = r_refdef.view.colorscale;
6041 oldwidth = r_refdef.view.width;
6042 oldheight = r_refdef.view.height;
6043 r_refdef.view.width = r_bloomstate.bloomwidth;
6044 r_refdef.view.height = r_bloomstate.bloomheight;
6046 if(r_hdr.integer < 2)
6047 r_waterstate.enabled = false;
6049 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
6050 // TODO: add exposure compensation features
6051 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6053 r_refdef.view.showdebug = false;
6054 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6056 R_ResetViewRendering3D();
6058 R_ClearScreen(r_refdef.fogenabled);
6059 if (r_timereport_active)
6060 R_TimeReport("HDRclear");
6063 if (r_timereport_active)
6064 R_TimeReport("visibility");
6066 // only do secondary renders with HDR if r_hdr is 2 or higher
6067 r_waterstate.numwaterplanes = 0;
6068 if (r_waterstate.enabled)
6069 R_RenderWaterPlanes();
6071 r_refdef.view.showdebug = true;
6073 r_waterstate.numwaterplanes = 0;
6075 R_ResetViewRendering2D();
6077 R_Bloom_CopyHDRTexture();
6078 R_Bloom_MakeTexture();
6080 // restore the view settings
6081 r_waterstate.enabled = oldwaterstate;
6082 r_refdef.view.width = oldwidth;
6083 r_refdef.view.height = oldheight;
6084 r_refdef.view.colorscale = oldcolorscale;
6086 R_ResetViewRendering3D();
6088 R_ClearScreen(r_refdef.fogenabled);
6089 if (r_timereport_active)
6090 R_TimeReport("viewclear");
6093 static void R_BlendView(void)
6095 unsigned int permutation;
6096 float uservecs[4][4];
6098 switch (vid.renderpath)
6100 case RENDERPATH_GL20:
6101 case RENDERPATH_D3D9:
6102 case RENDERPATH_D3D10:
6103 case RENDERPATH_D3D11:
6104 case RENDERPATH_SOFT:
6105 case RENDERPATH_GLES2:
6107 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6108 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6109 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6110 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6111 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6113 if (r_bloomstate.texture_screen)
6115 // make sure the buffer is available
6116 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6118 R_ResetViewRendering2D();
6119 R_Mesh_SetMainRenderTargets();
6121 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6123 // declare variables
6125 static float avgspeed;
6127 speed = VectorLength(cl.movement_velocity);
6129 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6130 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6132 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6133 speed = bound(0, speed, 1);
6134 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6136 // calculate values into a standard alpha
6137 cl.motionbluralpha = 1 - exp(-
6139 (r_motionblur.value * speed / 80)
6141 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6144 max(0.0001, cl.time - cl.oldtime) // fps independent
6147 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6148 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6150 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6152 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6153 GL_Color(1, 1, 1, cl.motionbluralpha);
6154 switch(vid.renderpath)
6156 case RENDERPATH_GL11:
6157 case RENDERPATH_GL13:
6158 case RENDERPATH_GL20:
6159 case RENDERPATH_SOFT:
6160 case RENDERPATH_GLES2:
6161 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6163 case RENDERPATH_D3D9:
6164 case RENDERPATH_D3D10:
6165 case RENDERPATH_D3D11:
6166 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6169 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6170 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6171 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6175 // copy view into the screen texture
6176 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);
6177 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6179 else if (!r_bloomstate.texture_bloom)
6181 // we may still have to do view tint...
6182 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6184 // apply a color tint to the whole view
6185 R_ResetViewRendering2D();
6186 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6187 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6188 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6189 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6190 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6192 break; // no screen processing, no bloom, skip it
6195 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6197 // render simple bloom effect
6198 // copy the screen and shrink it and darken it for the bloom process
6199 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6200 // make the bloom texture
6201 R_Bloom_MakeTexture();
6204 #if _MSC_VER >= 1400
6205 #define sscanf sscanf_s
6207 memset(uservecs, 0, sizeof(uservecs));
6208 if (r_glsl_postprocess_uservec1_enable.integer)
6209 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6210 if (r_glsl_postprocess_uservec2_enable.integer)
6211 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6212 if (r_glsl_postprocess_uservec3_enable.integer)
6213 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6214 if (r_glsl_postprocess_uservec4_enable.integer)
6215 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6217 R_ResetViewRendering2D();
6218 GL_Color(1, 1, 1, 1);
6219 GL_BlendFunc(GL_ONE, GL_ZERO);
6221 switch(vid.renderpath)
6223 case RENDERPATH_GL20:
6224 case RENDERPATH_GLES2:
6225 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6226 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6227 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6228 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6229 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6230 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]);
6231 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6232 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]);
6233 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]);
6234 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]);
6235 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]);
6236 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6237 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6238 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);
6240 case RENDERPATH_D3D9:
6242 // 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...
6243 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6244 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6245 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6246 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6247 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6248 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6249 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6250 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6251 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6252 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6253 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6254 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6255 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6256 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6259 case RENDERPATH_D3D10:
6260 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6262 case RENDERPATH_D3D11:
6263 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6265 case RENDERPATH_SOFT:
6266 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6267 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6268 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6269 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6270 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6271 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6272 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6273 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6274 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6275 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6276 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6277 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6278 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6279 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6284 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6285 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6287 case RENDERPATH_GL13:
6288 case RENDERPATH_GL11:
6289 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6291 // apply a color tint to the whole view
6292 R_ResetViewRendering2D();
6293 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6294 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6295 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6296 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6297 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6303 matrix4x4_t r_waterscrollmatrix;
6305 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6307 if (r_refdef.fog_density)
6309 r_refdef.fogcolor[0] = r_refdef.fog_red;
6310 r_refdef.fogcolor[1] = r_refdef.fog_green;
6311 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6313 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6314 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6315 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6316 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6320 VectorCopy(r_refdef.fogcolor, fogvec);
6321 // color.rgb *= ContrastBoost * SceneBrightness;
6322 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6323 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6324 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6325 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6330 void R_UpdateVariables(void)
6334 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6336 r_refdef.farclip = r_farclip_base.value;
6337 if (r_refdef.scene.worldmodel)
6338 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6339 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6341 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6342 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6343 r_refdef.polygonfactor = 0;
6344 r_refdef.polygonoffset = 0;
6345 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6346 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6348 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6349 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6350 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6351 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6352 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6353 if (FAKELIGHT_ENABLED)
6355 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6357 if (r_showsurfaces.integer)
6359 r_refdef.scene.rtworld = false;
6360 r_refdef.scene.rtworldshadows = false;
6361 r_refdef.scene.rtdlight = false;
6362 r_refdef.scene.rtdlightshadows = false;
6363 r_refdef.lightmapintensity = 0;
6366 if (gamemode == GAME_NEHAHRA)
6368 if (gl_fogenable.integer)
6370 r_refdef.oldgl_fogenable = true;
6371 r_refdef.fog_density = gl_fogdensity.value;
6372 r_refdef.fog_red = gl_fogred.value;
6373 r_refdef.fog_green = gl_foggreen.value;
6374 r_refdef.fog_blue = gl_fogblue.value;
6375 r_refdef.fog_alpha = 1;
6376 r_refdef.fog_start = 0;
6377 r_refdef.fog_end = gl_skyclip.value;
6378 r_refdef.fog_height = 1<<30;
6379 r_refdef.fog_fadedepth = 128;
6381 else if (r_refdef.oldgl_fogenable)
6383 r_refdef.oldgl_fogenable = false;
6384 r_refdef.fog_density = 0;
6385 r_refdef.fog_red = 0;
6386 r_refdef.fog_green = 0;
6387 r_refdef.fog_blue = 0;
6388 r_refdef.fog_alpha = 0;
6389 r_refdef.fog_start = 0;
6390 r_refdef.fog_end = 0;
6391 r_refdef.fog_height = 1<<30;
6392 r_refdef.fog_fadedepth = 128;
6396 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6397 r_refdef.fog_start = max(0, r_refdef.fog_start);
6398 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6400 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6402 if (r_refdef.fog_density && r_drawfog.integer)
6404 r_refdef.fogenabled = true;
6405 // this is the point where the fog reaches 0.9986 alpha, which we
6406 // consider a good enough cutoff point for the texture
6407 // (0.9986 * 256 == 255.6)
6408 if (r_fog_exp2.integer)
6409 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6411 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6412 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6413 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6414 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6415 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6416 R_BuildFogHeightTexture();
6417 // fog color was already set
6418 // update the fog texture
6419 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)
6420 R_BuildFogTexture();
6421 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6422 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6425 r_refdef.fogenabled = false;
6427 switch(vid.renderpath)
6429 case RENDERPATH_GL20:
6430 case RENDERPATH_D3D9:
6431 case RENDERPATH_D3D10:
6432 case RENDERPATH_D3D11:
6433 case RENDERPATH_SOFT:
6434 case RENDERPATH_GLES2:
6435 if(v_glslgamma.integer && !vid_gammatables_trivial)
6437 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6439 // build GLSL gamma texture
6440 #define RAMPWIDTH 256
6441 unsigned short ramp[RAMPWIDTH * 3];
6442 unsigned char rampbgr[RAMPWIDTH][4];
6445 r_texture_gammaramps_serial = vid_gammatables_serial;
6447 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6448 for(i = 0; i < RAMPWIDTH; ++i)
6450 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6451 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6452 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6455 if (r_texture_gammaramps)
6457 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6461 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6467 // remove GLSL gamma texture
6470 case RENDERPATH_GL13:
6471 case RENDERPATH_GL11:
6476 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6477 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6483 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6484 if( scenetype != r_currentscenetype ) {
6485 // store the old scenetype
6486 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6487 r_currentscenetype = scenetype;
6488 // move in the new scene
6489 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6498 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6500 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6501 if( scenetype == r_currentscenetype ) {
6502 return &r_refdef.scene;
6504 return &r_scenes_store[ scenetype ];
6513 int dpsoftrast_test;
6514 void R_RenderView(void)
6516 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6518 dpsoftrast_test = r_test.integer;
6520 if (r_timereport_active)
6521 R_TimeReport("start");
6522 r_textureframe++; // used only by R_GetCurrentTexture
6523 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6525 if(R_CompileShader_CheckStaticParms())
6528 if (!r_drawentities.integer)
6529 r_refdef.scene.numentities = 0;
6531 R_AnimCache_ClearCache();
6532 R_FrameData_NewFrame();
6534 /* adjust for stereo display */
6535 if(R_Stereo_Active())
6537 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);
6538 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6541 if (r_refdef.view.isoverlay)
6543 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6544 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6545 R_TimeReport("depthclear");
6547 r_refdef.view.showdebug = false;
6549 r_waterstate.enabled = false;
6550 r_waterstate.numwaterplanes = 0;
6554 r_refdef.view.matrix = originalmatrix;
6560 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6562 r_refdef.view.matrix = originalmatrix;
6563 return; //Host_Error ("R_RenderView: NULL worldmodel");
6566 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6568 R_RenderView_UpdateViewVectors();
6570 R_Shadow_UpdateWorldLightSelection();
6572 R_Bloom_StartFrame();
6573 R_Water_StartFrame();
6576 if (r_timereport_active)
6577 R_TimeReport("viewsetup");
6579 R_ResetViewRendering3D();
6581 if (r_refdef.view.clear || r_refdef.fogenabled)
6583 R_ClearScreen(r_refdef.fogenabled);
6584 if (r_timereport_active)
6585 R_TimeReport("viewclear");
6587 r_refdef.view.clear = true;
6589 // this produces a bloom texture to be used in R_BlendView() later
6590 if (r_bloomstate.hdr)
6592 R_HDR_RenderBloomTexture();
6593 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6594 r_textureframe++; // used only by R_GetCurrentTexture
6597 r_refdef.view.showdebug = true;
6600 if (r_timereport_active)
6601 R_TimeReport("visibility");
6603 r_waterstate.numwaterplanes = 0;
6604 if (r_waterstate.enabled)
6605 R_RenderWaterPlanes();
6608 r_waterstate.numwaterplanes = 0;
6611 if (r_timereport_active)
6612 R_TimeReport("blendview");
6614 GL_Scissor(0, 0, vid.width, vid.height);
6615 GL_ScissorTest(false);
6617 r_refdef.view.matrix = originalmatrix;
6622 void R_RenderWaterPlanes(void)
6624 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6626 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6627 if (r_timereport_active)
6628 R_TimeReport("waterworld");
6631 // don't let sound skip if going slow
6632 if (r_refdef.scene.extraupdate)
6635 R_DrawModelsAddWaterPlanes();
6636 if (r_timereport_active)
6637 R_TimeReport("watermodels");
6639 if (r_waterstate.numwaterplanes)
6641 R_Water_ProcessPlanes();
6642 if (r_timereport_active)
6643 R_TimeReport("waterscenes");
6647 extern void R_DrawLightningBeams (void);
6648 extern void VM_CL_AddPolygonsToMeshQueue (void);
6649 extern void R_DrawPortals (void);
6650 extern cvar_t cl_locs_show;
6651 static void R_DrawLocs(void);
6652 static void R_DrawEntityBBoxes(void);
6653 static void R_DrawModelDecals(void);
6654 extern void R_DrawModelShadows(void);
6655 extern void R_DrawModelShadowMaps(void);
6656 extern cvar_t cl_decals_newsystem;
6657 extern qboolean r_shadow_usingdeferredprepass;
6658 void R_RenderScene(void)
6660 qboolean shadowmapping = false;
6662 if (r_timereport_active)
6663 R_TimeReport("beginscene");
6665 r_refdef.stats.renders++;
6669 // don't let sound skip if going slow
6670 if (r_refdef.scene.extraupdate)
6673 R_MeshQueue_BeginScene();
6677 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);
6679 if (r_timereport_active)
6680 R_TimeReport("skystartframe");
6682 if (cl.csqc_vidvars.drawworld)
6684 // don't let sound skip if going slow
6685 if (r_refdef.scene.extraupdate)
6688 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6690 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6691 if (r_timereport_active)
6692 R_TimeReport("worldsky");
6695 if (R_DrawBrushModelsSky() && r_timereport_active)
6696 R_TimeReport("bmodelsky");
6698 if (skyrendermasked && skyrenderlater)
6700 // we have to force off the water clipping plane while rendering sky
6704 if (r_timereport_active)
6705 R_TimeReport("sky");
6709 R_AnimCache_CacheVisibleEntities();
6710 if (r_timereport_active)
6711 R_TimeReport("animation");
6713 R_Shadow_PrepareLights();
6714 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6715 R_Shadow_PrepareModelShadows();
6716 if (r_timereport_active)
6717 R_TimeReport("preparelights");
6719 if (R_Shadow_ShadowMappingEnabled())
6720 shadowmapping = true;
6722 if (r_shadow_usingdeferredprepass)
6723 R_Shadow_DrawPrepass();
6725 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6727 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6728 if (r_timereport_active)
6729 R_TimeReport("worlddepth");
6731 if (r_depthfirst.integer >= 2)
6733 R_DrawModelsDepth();
6734 if (r_timereport_active)
6735 R_TimeReport("modeldepth");
6738 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6740 R_DrawModelShadowMaps();
6741 R_ResetViewRendering3D();
6742 // don't let sound skip if going slow
6743 if (r_refdef.scene.extraupdate)
6747 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6749 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6750 if (r_timereport_active)
6751 R_TimeReport("world");
6754 // don't let sound skip if going slow
6755 if (r_refdef.scene.extraupdate)
6759 if (r_timereport_active)
6760 R_TimeReport("models");
6762 // don't let sound skip if going slow
6763 if (r_refdef.scene.extraupdate)
6766 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6768 R_DrawModelShadows();
6769 R_ResetViewRendering3D();
6770 // don't let sound skip if going slow
6771 if (r_refdef.scene.extraupdate)
6775 if (!r_shadow_usingdeferredprepass)
6777 R_Shadow_DrawLights();
6778 if (r_timereport_active)
6779 R_TimeReport("rtlights");
6782 // don't let sound skip if going slow
6783 if (r_refdef.scene.extraupdate)
6786 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6788 R_DrawModelShadows();
6789 R_ResetViewRendering3D();
6790 // don't let sound skip if going slow
6791 if (r_refdef.scene.extraupdate)
6795 if (cl.csqc_vidvars.drawworld)
6797 if (cl_decals_newsystem.integer)
6799 R_DrawModelDecals();
6800 if (r_timereport_active)
6801 R_TimeReport("modeldecals");
6806 if (r_timereport_active)
6807 R_TimeReport("decals");
6811 if (r_timereport_active)
6812 R_TimeReport("particles");
6815 if (r_timereport_active)
6816 R_TimeReport("explosions");
6818 R_DrawLightningBeams();
6819 if (r_timereport_active)
6820 R_TimeReport("lightning");
6823 VM_CL_AddPolygonsToMeshQueue();
6825 if (r_refdef.view.showdebug)
6827 if (cl_locs_show.integer)
6830 if (r_timereport_active)
6831 R_TimeReport("showlocs");
6834 if (r_drawportals.integer)
6837 if (r_timereport_active)
6838 R_TimeReport("portals");
6841 if (r_showbboxes.value > 0)
6843 R_DrawEntityBBoxes();
6844 if (r_timereport_active)
6845 R_TimeReport("bboxes");
6849 R_MeshQueue_RenderTransparent();
6850 if (r_timereport_active)
6851 R_TimeReport("drawtrans");
6853 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))
6855 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6856 if (r_timereport_active)
6857 R_TimeReport("worlddebug");
6858 R_DrawModelsDebug();
6859 if (r_timereport_active)
6860 R_TimeReport("modeldebug");
6863 if (cl.csqc_vidvars.drawworld)
6865 R_Shadow_DrawCoronas();
6866 if (r_timereport_active)
6867 R_TimeReport("coronas");
6872 GL_DepthTest(false);
6873 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6874 GL_Color(1, 1, 1, 1);
6875 qglBegin(GL_POLYGON);
6876 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6877 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6878 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6879 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6881 qglBegin(GL_POLYGON);
6882 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]);
6883 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]);
6884 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]);
6885 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]);
6887 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6891 // don't let sound skip if going slow
6892 if (r_refdef.scene.extraupdate)
6895 R_ResetViewRendering2D();
6898 static const unsigned short bboxelements[36] =
6908 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6911 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6913 RSurf_ActiveWorldEntity();
6915 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6916 GL_DepthMask(false);
6917 GL_DepthRange(0, 1);
6918 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6919 // R_Mesh_ResetTextureState();
6921 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6922 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6923 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6924 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6925 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6926 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6927 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6928 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6929 R_FillColors(color4f, 8, cr, cg, cb, ca);
6930 if (r_refdef.fogenabled)
6932 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6934 f1 = RSurf_FogVertex(v);
6936 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6937 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6938 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6941 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6942 R_Mesh_ResetTextureState();
6943 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6944 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6947 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6951 prvm_edict_t *edict;
6952 prvm_prog_t *prog_save = prog;
6954 // this function draws bounding boxes of server entities
6958 GL_CullFace(GL_NONE);
6959 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6963 for (i = 0;i < numsurfaces;i++)
6965 edict = PRVM_EDICT_NUM(surfacelist[i]);
6966 switch ((int)edict->fields.server->solid)
6968 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6969 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6970 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6971 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6972 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6973 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6975 color[3] *= r_showbboxes.value;
6976 color[3] = bound(0, color[3], 1);
6977 GL_DepthTest(!r_showdisabledepthtest.integer);
6978 GL_CullFace(r_refdef.view.cullface_front);
6979 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6985 static void R_DrawEntityBBoxes(void)
6988 prvm_edict_t *edict;
6990 prvm_prog_t *prog_save = prog;
6992 // this function draws bounding boxes of server entities
6998 for (i = 0;i < prog->num_edicts;i++)
7000 edict = PRVM_EDICT_NUM(i);
7001 if (edict->priv.server->free)
7003 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7004 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
7006 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
7008 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7009 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7015 static const int nomodelelement3i[24] =
7027 static const unsigned short nomodelelement3s[24] =
7039 static const float nomodelvertex3f[6*3] =
7049 static const float nomodelcolor4f[6*4] =
7051 0.0f, 0.0f, 0.5f, 1.0f,
7052 0.0f, 0.0f, 0.5f, 1.0f,
7053 0.0f, 0.5f, 0.0f, 1.0f,
7054 0.0f, 0.5f, 0.0f, 1.0f,
7055 0.5f, 0.0f, 0.0f, 1.0f,
7056 0.5f, 0.0f, 0.0f, 1.0f
7059 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7065 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);
7067 // this is only called once per entity so numsurfaces is always 1, and
7068 // surfacelist is always {0}, so this code does not handle batches
7070 if (rsurface.ent_flags & RENDER_ADDITIVE)
7072 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7073 GL_DepthMask(false);
7075 else if (rsurface.colormod[3] < 1)
7077 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7078 GL_DepthMask(false);
7082 GL_BlendFunc(GL_ONE, GL_ZERO);
7085 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7086 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7087 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7088 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7089 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7090 for (i = 0, c = color4f;i < 6;i++, c += 4)
7092 c[0] *= rsurface.colormod[0];
7093 c[1] *= rsurface.colormod[1];
7094 c[2] *= rsurface.colormod[2];
7095 c[3] *= rsurface.colormod[3];
7097 if (r_refdef.fogenabled)
7099 for (i = 0, c = color4f;i < 6;i++, c += 4)
7101 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7103 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7104 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7105 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7108 // R_Mesh_ResetTextureState();
7109 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
7110 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7111 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7114 void R_DrawNoModel(entity_render_t *ent)
7117 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7118 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7119 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7121 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7124 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7126 vec3_t right1, right2, diff, normal;
7128 VectorSubtract (org2, org1, normal);
7130 // calculate 'right' vector for start
7131 VectorSubtract (r_refdef.view.origin, org1, diff);
7132 CrossProduct (normal, diff, right1);
7133 VectorNormalize (right1);
7135 // calculate 'right' vector for end
7136 VectorSubtract (r_refdef.view.origin, org2, diff);
7137 CrossProduct (normal, diff, right2);
7138 VectorNormalize (right2);
7140 vert[ 0] = org1[0] + width * right1[0];
7141 vert[ 1] = org1[1] + width * right1[1];
7142 vert[ 2] = org1[2] + width * right1[2];
7143 vert[ 3] = org1[0] - width * right1[0];
7144 vert[ 4] = org1[1] - width * right1[1];
7145 vert[ 5] = org1[2] - width * right1[2];
7146 vert[ 6] = org2[0] - width * right2[0];
7147 vert[ 7] = org2[1] - width * right2[1];
7148 vert[ 8] = org2[2] - width * right2[2];
7149 vert[ 9] = org2[0] + width * right2[0];
7150 vert[10] = org2[1] + width * right2[1];
7151 vert[11] = org2[2] + width * right2[2];
7154 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)
7156 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7157 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7158 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7159 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7160 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7161 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7162 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7163 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7164 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7165 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7166 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7167 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7170 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7175 VectorSet(v, x, y, z);
7176 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7177 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7179 if (i == mesh->numvertices)
7181 if (mesh->numvertices < mesh->maxvertices)
7183 VectorCopy(v, vertex3f);
7184 mesh->numvertices++;
7186 return mesh->numvertices;
7192 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7196 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7197 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7198 e = mesh->element3i + mesh->numtriangles * 3;
7199 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7201 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7202 if (mesh->numtriangles < mesh->maxtriangles)
7207 mesh->numtriangles++;
7209 element[1] = element[2];
7213 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7217 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7218 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7219 e = mesh->element3i + mesh->numtriangles * 3;
7220 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7222 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7223 if (mesh->numtriangles < mesh->maxtriangles)
7228 mesh->numtriangles++;
7230 element[1] = element[2];
7234 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7235 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7237 int planenum, planenum2;
7240 mplane_t *plane, *plane2;
7242 double temppoints[2][256*3];
7243 // figure out how large a bounding box we need to properly compute this brush
7245 for (w = 0;w < numplanes;w++)
7246 maxdist = max(maxdist, fabs(planes[w].dist));
7247 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7248 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7249 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7253 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7254 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7256 if (planenum2 == planenum)
7258 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);
7261 if (tempnumpoints < 3)
7263 // generate elements forming a triangle fan for this polygon
7264 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7268 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)
7270 texturelayer_t *layer;
7271 layer = t->currentlayers + t->currentnumlayers++;
7273 layer->depthmask = depthmask;
7274 layer->blendfunc1 = blendfunc1;
7275 layer->blendfunc2 = blendfunc2;
7276 layer->texture = texture;
7277 layer->texmatrix = *matrix;
7278 layer->color[0] = r;
7279 layer->color[1] = g;
7280 layer->color[2] = b;
7281 layer->color[3] = a;
7284 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7286 if(parms[0] == 0 && parms[1] == 0)
7288 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7289 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7294 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7297 index = parms[2] + r_refdef.scene.time * parms[3];
7298 index -= floor(index);
7299 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7302 case Q3WAVEFUNC_NONE:
7303 case Q3WAVEFUNC_NOISE:
7304 case Q3WAVEFUNC_COUNT:
7307 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7308 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7309 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7310 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7311 case Q3WAVEFUNC_TRIANGLE:
7313 f = index - floor(index);
7324 f = parms[0] + parms[1] * f;
7325 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7326 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7330 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7335 matrix4x4_t matrix, temp;
7336 switch(tcmod->tcmod)
7340 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7341 matrix = r_waterscrollmatrix;
7343 matrix = identitymatrix;
7345 case Q3TCMOD_ENTITYTRANSLATE:
7346 // this is used in Q3 to allow the gamecode to control texcoord
7347 // scrolling on the entity, which is not supported in darkplaces yet.
7348 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7350 case Q3TCMOD_ROTATE:
7351 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7352 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7353 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7356 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7358 case Q3TCMOD_SCROLL:
7359 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7361 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7362 w = (int) tcmod->parms[0];
7363 h = (int) tcmod->parms[1];
7364 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7366 idx = (int) floor(f * w * h);
7367 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7369 case Q3TCMOD_STRETCH:
7370 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7371 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7373 case Q3TCMOD_TRANSFORM:
7374 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7375 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7376 VectorSet(tcmat + 6, 0 , 0 , 1);
7377 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7378 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7380 case Q3TCMOD_TURBULENT:
7381 // this is handled in the RSurf_PrepareVertices function
7382 matrix = identitymatrix;
7386 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7389 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7391 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7392 char name[MAX_QPATH];
7393 skinframe_t *skinframe;
7394 unsigned char pixels[296*194];
7395 strlcpy(cache->name, skinname, sizeof(cache->name));
7396 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7397 if (developer_loading.integer)
7398 Con_Printf("loading %s\n", name);
7399 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7400 if (!skinframe || !skinframe->base)
7403 fs_offset_t filesize;
7405 f = FS_LoadFile(name, tempmempool, true, &filesize);
7408 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7409 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7413 cache->skinframe = skinframe;
7416 texture_t *R_GetCurrentTexture(texture_t *t)
7419 const entity_render_t *ent = rsurface.entity;
7420 dp_model_t *model = ent->model;
7421 q3shaderinfo_layer_tcmod_t *tcmod;
7423 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7424 return t->currentframe;
7425 t->update_lastrenderframe = r_textureframe;
7426 t->update_lastrenderentity = (void *)ent;
7428 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7429 t->camera_entity = ent->entitynumber;
7431 t->camera_entity = 0;
7433 // switch to an alternate material if this is a q1bsp animated material
7435 texture_t *texture = t;
7436 int s = rsurface.ent_skinnum;
7437 if ((unsigned int)s >= (unsigned int)model->numskins)
7439 if (model->skinscenes)
7441 if (model->skinscenes[s].framecount > 1)
7442 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7444 s = model->skinscenes[s].firstframe;
7447 t = t + s * model->num_surfaces;
7450 // use an alternate animation if the entity's frame is not 0,
7451 // and only if the texture has an alternate animation
7452 if (rsurface.ent_alttextures && t->anim_total[1])
7453 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7455 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7457 texture->currentframe = t;
7460 // update currentskinframe to be a qw skin or animation frame
7461 if (rsurface.ent_qwskin >= 0)
7463 i = rsurface.ent_qwskin;
7464 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7466 r_qwskincache_size = cl.maxclients;
7468 Mem_Free(r_qwskincache);
7469 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7471 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7472 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7473 t->currentskinframe = r_qwskincache[i].skinframe;
7474 if (t->currentskinframe == NULL)
7475 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7477 else if (t->numskinframes >= 2)
7478 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7479 if (t->backgroundnumskinframes >= 2)
7480 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7482 t->currentmaterialflags = t->basematerialflags;
7483 t->currentalpha = rsurface.colormod[3];
7484 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7485 t->currentalpha *= r_wateralpha.value;
7486 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7487 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7488 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7489 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7490 if (!(rsurface.ent_flags & RENDER_LIGHT))
7491 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7492 else if (FAKELIGHT_ENABLED)
7494 // no modellight if using fakelight for the map
7496 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7498 // pick a model lighting mode
7499 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7500 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7502 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7504 if (rsurface.ent_flags & RENDER_ADDITIVE)
7505 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7506 else if (t->currentalpha < 1)
7507 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7508 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7509 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7510 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7511 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7512 if (t->backgroundnumskinframes)
7513 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7514 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7516 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7517 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7520 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7521 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7522 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7524 // there is no tcmod
7525 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7527 t->currenttexmatrix = r_waterscrollmatrix;
7528 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7530 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7532 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7533 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7536 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7537 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7538 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7539 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7541 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7542 if (t->currentskinframe->qpixels)
7543 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7544 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7545 if (!t->basetexture)
7546 t->basetexture = r_texture_notexture;
7547 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7548 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7549 t->nmaptexture = t->currentskinframe->nmap;
7550 if (!t->nmaptexture)
7551 t->nmaptexture = r_texture_blanknormalmap;
7552 t->glosstexture = r_texture_black;
7553 t->glowtexture = t->currentskinframe->glow;
7554 t->fogtexture = t->currentskinframe->fog;
7555 t->reflectmasktexture = t->currentskinframe->reflect;
7556 if (t->backgroundnumskinframes)
7558 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7559 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7560 t->backgroundglosstexture = r_texture_black;
7561 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7562 if (!t->backgroundnmaptexture)
7563 t->backgroundnmaptexture = r_texture_blanknormalmap;
7567 t->backgroundbasetexture = r_texture_white;
7568 t->backgroundnmaptexture = r_texture_blanknormalmap;
7569 t->backgroundglosstexture = r_texture_black;
7570 t->backgroundglowtexture = NULL;
7572 t->specularpower = r_shadow_glossexponent.value;
7573 // TODO: store reference values for these in the texture?
7574 t->specularscale = 0;
7575 if (r_shadow_gloss.integer > 0)
7577 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7579 if (r_shadow_glossintensity.value > 0)
7581 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7582 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7583 t->specularscale = r_shadow_glossintensity.value;
7586 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7588 t->glosstexture = r_texture_white;
7589 t->backgroundglosstexture = r_texture_white;
7590 t->specularscale = r_shadow_gloss2intensity.value;
7591 t->specularpower = r_shadow_gloss2exponent.value;
7594 t->specularscale *= t->specularscalemod;
7595 t->specularpower *= t->specularpowermod;
7597 // lightmaps mode looks bad with dlights using actual texturing, so turn
7598 // off the colormap and glossmap, but leave the normalmap on as it still
7599 // accurately represents the shading involved
7600 if (gl_lightmaps.integer)
7602 t->basetexture = r_texture_grey128;
7603 t->pantstexture = r_texture_black;
7604 t->shirttexture = r_texture_black;
7605 t->nmaptexture = r_texture_blanknormalmap;
7606 t->glosstexture = r_texture_black;
7607 t->glowtexture = NULL;
7608 t->fogtexture = NULL;
7609 t->reflectmasktexture = NULL;
7610 t->backgroundbasetexture = NULL;
7611 t->backgroundnmaptexture = r_texture_blanknormalmap;
7612 t->backgroundglosstexture = r_texture_black;
7613 t->backgroundglowtexture = NULL;
7614 t->specularscale = 0;
7615 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7618 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7619 VectorClear(t->dlightcolor);
7620 t->currentnumlayers = 0;
7621 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7623 int blendfunc1, blendfunc2;
7625 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7627 blendfunc1 = GL_SRC_ALPHA;
7628 blendfunc2 = GL_ONE;
7630 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7632 blendfunc1 = GL_SRC_ALPHA;
7633 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7635 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7637 blendfunc1 = t->customblendfunc[0];
7638 blendfunc2 = t->customblendfunc[1];
7642 blendfunc1 = GL_ONE;
7643 blendfunc2 = GL_ZERO;
7645 // don't colormod evilblend textures
7646 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7647 VectorSet(t->lightmapcolor, 1, 1, 1);
7648 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7649 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7651 // fullbright is not affected by r_refdef.lightmapintensity
7652 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]);
7653 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7654 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]);
7655 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7656 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]);
7660 vec3_t ambientcolor;
7662 // set the color tint used for lights affecting this surface
7663 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7665 // q3bsp has no lightmap updates, so the lightstylevalue that
7666 // would normally be baked into the lightmap must be
7667 // applied to the color
7668 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7669 if (model->type == mod_brushq3)
7670 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7671 colorscale *= r_refdef.lightmapintensity;
7672 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7673 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7674 // basic lit geometry
7675 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]);
7676 // add pants/shirt if needed
7677 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7678 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]);
7679 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7680 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]);
7681 // now add ambient passes if needed
7682 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7684 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]);
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] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[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] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
7691 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7692 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]);
7693 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7695 // if this is opaque use alpha blend which will darken the earlier
7698 // if this is an alpha blended material, all the earlier passes
7699 // were darkened by fog already, so we only need to add the fog
7700 // color ontop through the fog mask texture
7702 // if this is an additive blended material, all the earlier passes
7703 // were darkened by fog already, and we should not add fog color
7704 // (because the background was not darkened, there is no fog color
7705 // that was lost behind it).
7706 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]);
7710 return t->currentframe;
7713 rsurfacestate_t rsurface;
7715 void RSurf_ActiveWorldEntity(void)
7717 dp_model_t *model = r_refdef.scene.worldmodel;
7718 //if (rsurface.entity == r_refdef.scene.worldentity)
7720 rsurface.entity = r_refdef.scene.worldentity;
7721 rsurface.skeleton = NULL;
7722 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7723 rsurface.ent_skinnum = 0;
7724 rsurface.ent_qwskin = -1;
7725 rsurface.ent_shadertime = 0;
7726 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7727 rsurface.matrix = identitymatrix;
7728 rsurface.inversematrix = identitymatrix;
7729 rsurface.matrixscale = 1;
7730 rsurface.inversematrixscale = 1;
7731 R_EntityMatrix(&identitymatrix);
7732 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7733 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7734 rsurface.fograngerecip = r_refdef.fograngerecip;
7735 rsurface.fogheightfade = r_refdef.fogheightfade;
7736 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7737 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7738 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7739 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7740 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7741 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7742 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7743 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7744 rsurface.colormod[3] = 1;
7745 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);
7746 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7747 rsurface.frameblend[0].lerp = 1;
7748 rsurface.ent_alttextures = false;
7749 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7750 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7751 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7752 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7753 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7754 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7755 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7756 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7757 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7758 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7759 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7760 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7761 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7762 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7763 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7764 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7765 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7766 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7767 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7768 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7769 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7770 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7771 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7772 rsurface.modelelement3i = model->surfmesh.data_element3i;
7773 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7774 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7775 rsurface.modelelement3s = model->surfmesh.data_element3s;
7776 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7777 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7778 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7779 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7780 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7781 rsurface.modelsurfaces = model->data_surfaces;
7782 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7783 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7784 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7785 rsurface.modelgeneratedvertex = false;
7786 rsurface.batchgeneratedvertex = false;
7787 rsurface.batchfirstvertex = 0;
7788 rsurface.batchnumvertices = 0;
7789 rsurface.batchfirsttriangle = 0;
7790 rsurface.batchnumtriangles = 0;
7791 rsurface.batchvertex3f = NULL;
7792 rsurface.batchvertex3f_vertexbuffer = NULL;
7793 rsurface.batchvertex3f_bufferoffset = 0;
7794 rsurface.batchsvector3f = NULL;
7795 rsurface.batchsvector3f_vertexbuffer = NULL;
7796 rsurface.batchsvector3f_bufferoffset = 0;
7797 rsurface.batchtvector3f = NULL;
7798 rsurface.batchtvector3f_vertexbuffer = NULL;
7799 rsurface.batchtvector3f_bufferoffset = 0;
7800 rsurface.batchnormal3f = NULL;
7801 rsurface.batchnormal3f_vertexbuffer = NULL;
7802 rsurface.batchnormal3f_bufferoffset = 0;
7803 rsurface.batchlightmapcolor4f = NULL;
7804 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7805 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7806 rsurface.batchtexcoordtexture2f = NULL;
7807 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7808 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7809 rsurface.batchtexcoordlightmap2f = NULL;
7810 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7811 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7812 rsurface.batchvertexmesh = NULL;
7813 rsurface.batchvertexmeshbuffer = NULL;
7814 rsurface.batchvertex3fbuffer = NULL;
7815 rsurface.batchelement3i = NULL;
7816 rsurface.batchelement3i_indexbuffer = NULL;
7817 rsurface.batchelement3i_bufferoffset = 0;
7818 rsurface.batchelement3s = NULL;
7819 rsurface.batchelement3s_indexbuffer = NULL;
7820 rsurface.batchelement3s_bufferoffset = 0;
7821 rsurface.passcolor4f = NULL;
7822 rsurface.passcolor4f_vertexbuffer = NULL;
7823 rsurface.passcolor4f_bufferoffset = 0;
7826 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7828 dp_model_t *model = ent->model;
7829 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7831 rsurface.entity = (entity_render_t *)ent;
7832 rsurface.skeleton = ent->skeleton;
7833 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7834 rsurface.ent_skinnum = ent->skinnum;
7835 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;
7836 rsurface.ent_shadertime = ent->shadertime;
7837 rsurface.ent_flags = ent->flags;
7838 rsurface.matrix = ent->matrix;
7839 rsurface.inversematrix = ent->inversematrix;
7840 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7841 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7842 R_EntityMatrix(&rsurface.matrix);
7843 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7844 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7845 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7846 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7847 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7848 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7849 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7850 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7851 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7852 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7853 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7854 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7855 rsurface.colormod[3] = ent->alpha;
7856 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7857 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7858 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7859 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7860 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7861 if (ent->model->brush.submodel && !prepass)
7863 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7864 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7866 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7868 if (ent->animcache_vertex3f)
7870 rsurface.modelvertex3f = ent->animcache_vertex3f;
7871 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7872 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7873 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7874 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7875 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7876 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7878 else if (wanttangents)
7880 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7881 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7882 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7883 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7884 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7885 rsurface.modelvertexmesh = NULL;
7886 rsurface.modelvertexmeshbuffer = NULL;
7887 rsurface.modelvertex3fbuffer = NULL;
7889 else if (wantnormals)
7891 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7892 rsurface.modelsvector3f = NULL;
7893 rsurface.modeltvector3f = NULL;
7894 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7895 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7896 rsurface.modelvertexmesh = NULL;
7897 rsurface.modelvertexmeshbuffer = NULL;
7898 rsurface.modelvertex3fbuffer = NULL;
7902 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7903 rsurface.modelsvector3f = NULL;
7904 rsurface.modeltvector3f = NULL;
7905 rsurface.modelnormal3f = NULL;
7906 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7907 rsurface.modelvertexmesh = NULL;
7908 rsurface.modelvertexmeshbuffer = NULL;
7909 rsurface.modelvertex3fbuffer = NULL;
7911 rsurface.modelvertex3f_vertexbuffer = 0;
7912 rsurface.modelvertex3f_bufferoffset = 0;
7913 rsurface.modelsvector3f_vertexbuffer = 0;
7914 rsurface.modelsvector3f_bufferoffset = 0;
7915 rsurface.modeltvector3f_vertexbuffer = 0;
7916 rsurface.modeltvector3f_bufferoffset = 0;
7917 rsurface.modelnormal3f_vertexbuffer = 0;
7918 rsurface.modelnormal3f_bufferoffset = 0;
7919 rsurface.modelgeneratedvertex = true;
7923 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7924 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7925 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7926 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7927 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7928 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7929 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7930 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7931 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7932 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7933 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7934 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7935 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7936 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7937 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7938 rsurface.modelgeneratedvertex = false;
7940 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7941 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7942 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7943 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7944 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7945 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7946 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7947 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7948 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7949 rsurface.modelelement3i = model->surfmesh.data_element3i;
7950 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7951 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7952 rsurface.modelelement3s = model->surfmesh.data_element3s;
7953 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7954 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7955 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7956 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7957 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7958 rsurface.modelsurfaces = model->data_surfaces;
7959 rsurface.batchgeneratedvertex = false;
7960 rsurface.batchfirstvertex = 0;
7961 rsurface.batchnumvertices = 0;
7962 rsurface.batchfirsttriangle = 0;
7963 rsurface.batchnumtriangles = 0;
7964 rsurface.batchvertex3f = NULL;
7965 rsurface.batchvertex3f_vertexbuffer = NULL;
7966 rsurface.batchvertex3f_bufferoffset = 0;
7967 rsurface.batchsvector3f = NULL;
7968 rsurface.batchsvector3f_vertexbuffer = NULL;
7969 rsurface.batchsvector3f_bufferoffset = 0;
7970 rsurface.batchtvector3f = NULL;
7971 rsurface.batchtvector3f_vertexbuffer = NULL;
7972 rsurface.batchtvector3f_bufferoffset = 0;
7973 rsurface.batchnormal3f = NULL;
7974 rsurface.batchnormal3f_vertexbuffer = NULL;
7975 rsurface.batchnormal3f_bufferoffset = 0;
7976 rsurface.batchlightmapcolor4f = NULL;
7977 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7978 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7979 rsurface.batchtexcoordtexture2f = NULL;
7980 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7981 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7982 rsurface.batchtexcoordlightmap2f = NULL;
7983 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7984 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7985 rsurface.batchvertexmesh = NULL;
7986 rsurface.batchvertexmeshbuffer = NULL;
7987 rsurface.batchvertex3fbuffer = NULL;
7988 rsurface.batchelement3i = NULL;
7989 rsurface.batchelement3i_indexbuffer = NULL;
7990 rsurface.batchelement3i_bufferoffset = 0;
7991 rsurface.batchelement3s = NULL;
7992 rsurface.batchelement3s_indexbuffer = NULL;
7993 rsurface.batchelement3s_bufferoffset = 0;
7994 rsurface.passcolor4f = NULL;
7995 rsurface.passcolor4f_vertexbuffer = NULL;
7996 rsurface.passcolor4f_bufferoffset = 0;
7999 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)
8001 rsurface.entity = r_refdef.scene.worldentity;
8002 rsurface.skeleton = NULL;
8003 rsurface.ent_skinnum = 0;
8004 rsurface.ent_qwskin = -1;
8005 rsurface.ent_shadertime = shadertime;
8006 rsurface.ent_flags = entflags;
8007 rsurface.modelnumvertices = numvertices;
8008 rsurface.modelnumtriangles = numtriangles;
8009 rsurface.matrix = *matrix;
8010 rsurface.inversematrix = *inversematrix;
8011 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8012 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8013 R_EntityMatrix(&rsurface.matrix);
8014 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8015 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8016 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8017 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8018 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8019 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8020 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8021 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8022 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8023 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8024 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8025 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8026 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);
8027 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8028 rsurface.frameblend[0].lerp = 1;
8029 rsurface.ent_alttextures = false;
8030 rsurface.basepolygonfactor = r_refdef.polygonfactor;
8031 rsurface.basepolygonoffset = r_refdef.polygonoffset;
8034 rsurface.modelvertex3f = (float *)vertex3f;
8035 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8036 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8037 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8039 else if (wantnormals)
8041 rsurface.modelvertex3f = (float *)vertex3f;
8042 rsurface.modelsvector3f = NULL;
8043 rsurface.modeltvector3f = NULL;
8044 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8048 rsurface.modelvertex3f = (float *)vertex3f;
8049 rsurface.modelsvector3f = NULL;
8050 rsurface.modeltvector3f = NULL;
8051 rsurface.modelnormal3f = NULL;
8053 rsurface.modelvertexmesh = NULL;
8054 rsurface.modelvertexmeshbuffer = NULL;
8055 rsurface.modelvertex3fbuffer = NULL;
8056 rsurface.modelvertex3f_vertexbuffer = 0;
8057 rsurface.modelvertex3f_bufferoffset = 0;
8058 rsurface.modelsvector3f_vertexbuffer = 0;
8059 rsurface.modelsvector3f_bufferoffset = 0;
8060 rsurface.modeltvector3f_vertexbuffer = 0;
8061 rsurface.modeltvector3f_bufferoffset = 0;
8062 rsurface.modelnormal3f_vertexbuffer = 0;
8063 rsurface.modelnormal3f_bufferoffset = 0;
8064 rsurface.modelgeneratedvertex = true;
8065 rsurface.modellightmapcolor4f = (float *)color4f;
8066 rsurface.modellightmapcolor4f_vertexbuffer = 0;
8067 rsurface.modellightmapcolor4f_bufferoffset = 0;
8068 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
8069 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8070 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8071 rsurface.modeltexcoordlightmap2f = NULL;
8072 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8073 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8074 rsurface.modelelement3i = (int *)element3i;
8075 rsurface.modelelement3i_indexbuffer = NULL;
8076 rsurface.modelelement3i_bufferoffset = 0;
8077 rsurface.modelelement3s = (unsigned short *)element3s;
8078 rsurface.modelelement3s_indexbuffer = NULL;
8079 rsurface.modelelement3s_bufferoffset = 0;
8080 rsurface.modellightmapoffsets = NULL;
8081 rsurface.modelsurfaces = NULL;
8082 rsurface.batchgeneratedvertex = false;
8083 rsurface.batchfirstvertex = 0;
8084 rsurface.batchnumvertices = 0;
8085 rsurface.batchfirsttriangle = 0;
8086 rsurface.batchnumtriangles = 0;
8087 rsurface.batchvertex3f = NULL;
8088 rsurface.batchvertex3f_vertexbuffer = NULL;
8089 rsurface.batchvertex3f_bufferoffset = 0;
8090 rsurface.batchsvector3f = NULL;
8091 rsurface.batchsvector3f_vertexbuffer = NULL;
8092 rsurface.batchsvector3f_bufferoffset = 0;
8093 rsurface.batchtvector3f = NULL;
8094 rsurface.batchtvector3f_vertexbuffer = NULL;
8095 rsurface.batchtvector3f_bufferoffset = 0;
8096 rsurface.batchnormal3f = NULL;
8097 rsurface.batchnormal3f_vertexbuffer = NULL;
8098 rsurface.batchnormal3f_bufferoffset = 0;
8099 rsurface.batchlightmapcolor4f = NULL;
8100 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8101 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8102 rsurface.batchtexcoordtexture2f = NULL;
8103 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8104 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8105 rsurface.batchtexcoordlightmap2f = NULL;
8106 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8107 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8108 rsurface.batchvertexmesh = NULL;
8109 rsurface.batchvertexmeshbuffer = NULL;
8110 rsurface.batchvertex3fbuffer = NULL;
8111 rsurface.batchelement3i = NULL;
8112 rsurface.batchelement3i_indexbuffer = NULL;
8113 rsurface.batchelement3i_bufferoffset = 0;
8114 rsurface.batchelement3s = NULL;
8115 rsurface.batchelement3s_indexbuffer = NULL;
8116 rsurface.batchelement3s_bufferoffset = 0;
8117 rsurface.passcolor4f = NULL;
8118 rsurface.passcolor4f_vertexbuffer = NULL;
8119 rsurface.passcolor4f_bufferoffset = 0;
8121 if (rsurface.modelnumvertices && rsurface.modelelement3i)
8123 if ((wantnormals || wanttangents) && !normal3f)
8125 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8126 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8128 if (wanttangents && !svector3f)
8130 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8131 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8132 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8137 float RSurf_FogPoint(const float *v)
8139 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8140 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8141 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8142 float FogHeightFade = r_refdef.fogheightfade;
8144 unsigned int fogmasktableindex;
8145 if (r_refdef.fogplaneviewabove)
8146 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8148 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8149 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8150 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8153 float RSurf_FogVertex(const float *v)
8155 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8156 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8157 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8158 float FogHeightFade = rsurface.fogheightfade;
8160 unsigned int fogmasktableindex;
8161 if (r_refdef.fogplaneviewabove)
8162 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8164 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8165 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8166 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8169 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8172 for (i = 0;i < numelements;i++)
8173 outelement3i[i] = inelement3i[i] + adjust;
8176 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8177 extern cvar_t gl_vbo;
8178 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8186 int surfacefirsttriangle;
8187 int surfacenumtriangles;
8188 int surfacefirstvertex;
8189 int surfaceendvertex;
8190 int surfacenumvertices;
8191 int batchnumvertices;
8192 int batchnumtriangles;
8196 qboolean dynamicvertex;
8200 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8202 q3shaderinfo_deform_t *deform;
8203 const msurface_t *surface, *firstsurface;
8204 r_vertexmesh_t *vertexmesh;
8205 if (!texturenumsurfaces)
8207 // find vertex range of this surface batch
8209 firstsurface = texturesurfacelist[0];
8210 firsttriangle = firstsurface->num_firsttriangle;
8211 batchnumvertices = 0;
8212 batchnumtriangles = 0;
8213 firstvertex = endvertex = firstsurface->num_firstvertex;
8214 for (i = 0;i < texturenumsurfaces;i++)
8216 surface = texturesurfacelist[i];
8217 if (surface != firstsurface + i)
8219 surfacefirstvertex = surface->num_firstvertex;
8220 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8221 surfacenumvertices = surface->num_vertices;
8222 surfacenumtriangles = surface->num_triangles;
8223 if (firstvertex > surfacefirstvertex)
8224 firstvertex = surfacefirstvertex;
8225 if (endvertex < surfaceendvertex)
8226 endvertex = surfaceendvertex;
8227 batchnumvertices += surfacenumvertices;
8228 batchnumtriangles += surfacenumtriangles;
8231 // we now know the vertex range used, and if there are any gaps in it
8232 rsurface.batchfirstvertex = firstvertex;
8233 rsurface.batchnumvertices = endvertex - firstvertex;
8234 rsurface.batchfirsttriangle = firsttriangle;
8235 rsurface.batchnumtriangles = batchnumtriangles;
8237 // this variable holds flags for which properties have been updated that
8238 // may require regenerating vertexmesh array...
8241 // check if any dynamic vertex processing must occur
8242 dynamicvertex = false;
8244 // if there is a chance of animated vertex colors, it's a dynamic batch
8245 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8247 dynamicvertex = true;
8248 batchneed |= BATCHNEED_NOGAPS;
8249 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8252 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8254 switch (deform->deform)
8257 case Q3DEFORM_PROJECTIONSHADOW:
8258 case Q3DEFORM_TEXT0:
8259 case Q3DEFORM_TEXT1:
8260 case Q3DEFORM_TEXT2:
8261 case Q3DEFORM_TEXT3:
8262 case Q3DEFORM_TEXT4:
8263 case Q3DEFORM_TEXT5:
8264 case Q3DEFORM_TEXT6:
8265 case Q3DEFORM_TEXT7:
8268 case Q3DEFORM_AUTOSPRITE:
8269 dynamicvertex = true;
8270 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8271 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8273 case Q3DEFORM_AUTOSPRITE2:
8274 dynamicvertex = true;
8275 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8276 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8278 case Q3DEFORM_NORMAL:
8279 dynamicvertex = true;
8280 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8281 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8284 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8285 break; // if wavefunc is a nop, ignore this transform
8286 dynamicvertex = true;
8287 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8288 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8290 case Q3DEFORM_BULGE:
8291 dynamicvertex = true;
8292 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8293 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8296 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8297 break; // if wavefunc is a nop, ignore this transform
8298 dynamicvertex = true;
8299 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8300 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8304 switch(rsurface.texture->tcgen.tcgen)
8307 case Q3TCGEN_TEXTURE:
8309 case Q3TCGEN_LIGHTMAP:
8310 dynamicvertex = true;
8311 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8312 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8314 case Q3TCGEN_VECTOR:
8315 dynamicvertex = true;
8316 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8317 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8319 case Q3TCGEN_ENVIRONMENT:
8320 dynamicvertex = true;
8321 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8322 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8325 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8327 dynamicvertex = true;
8328 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8329 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8332 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8334 dynamicvertex = true;
8335 batchneed |= BATCHNEED_NOGAPS;
8336 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8339 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8341 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8342 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8343 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8344 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8345 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8346 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8347 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8350 // when the model data has no vertex buffer (dynamic mesh), we need to
8352 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8353 batchneed |= BATCHNEED_NOGAPS;
8355 // if needsupdate, we have to do a dynamic vertex batch for sure
8356 if (needsupdate & batchneed)
8357 dynamicvertex = true;
8359 // see if we need to build vertexmesh from arrays
8360 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8361 dynamicvertex = true;
8363 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8364 // also some drivers strongly dislike firstvertex
8365 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8366 dynamicvertex = true;
8368 rsurface.batchvertex3f = rsurface.modelvertex3f;
8369 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8370 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8371 rsurface.batchsvector3f = rsurface.modelsvector3f;
8372 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8373 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8374 rsurface.batchtvector3f = rsurface.modeltvector3f;
8375 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8376 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8377 rsurface.batchnormal3f = rsurface.modelnormal3f;
8378 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8379 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8380 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8381 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8382 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8383 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8384 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8385 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8386 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8387 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8388 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8389 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8390 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8391 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8392 rsurface.batchelement3i = rsurface.modelelement3i;
8393 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8394 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8395 rsurface.batchelement3s = rsurface.modelelement3s;
8396 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8397 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8399 // if any dynamic vertex processing has to occur in software, we copy the
8400 // entire surface list together before processing to rebase the vertices
8401 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8403 // if any gaps exist and we do not have a static vertex buffer, we have to
8404 // copy the surface list together to avoid wasting upload bandwidth on the
8405 // vertices in the gaps.
8407 // if gaps exist and we have a static vertex buffer, we still have to
8408 // combine the index buffer ranges into one dynamic index buffer.
8410 // in all cases we end up with data that can be drawn in one call.
8414 // static vertex data, just set pointers...
8415 rsurface.batchgeneratedvertex = false;
8416 // if there are gaps, we want to build a combined index buffer,
8417 // otherwise use the original static buffer with an appropriate offset
8420 // build a new triangle elements array for this batch
8421 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8422 rsurface.batchfirsttriangle = 0;
8424 for (i = 0;i < texturenumsurfaces;i++)
8426 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8427 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8428 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8429 numtriangles += surfacenumtriangles;
8431 rsurface.batchelement3i_indexbuffer = NULL;
8432 rsurface.batchelement3i_bufferoffset = 0;
8433 rsurface.batchelement3s = NULL;
8434 rsurface.batchelement3s_indexbuffer = NULL;
8435 rsurface.batchelement3s_bufferoffset = 0;
8436 if (endvertex <= 65536)
8438 // make a 16bit (unsigned short) index array if possible
8439 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8440 for (i = 0;i < numtriangles*3;i++)
8441 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8447 // something needs software processing, do it for real...
8448 // we only directly handle separate array data in this case and then
8449 // generate interleaved data if needed...
8450 rsurface.batchgeneratedvertex = true;
8452 // now copy the vertex data into a combined array and make an index array
8453 // (this is what Quake3 does all the time)
8454 //if (gaps || rsurface.batchfirstvertex)
8456 rsurface.batchvertex3fbuffer = NULL;
8457 rsurface.batchvertexmesh = NULL;
8458 rsurface.batchvertexmeshbuffer = NULL;
8459 rsurface.batchvertex3f = NULL;
8460 rsurface.batchvertex3f_vertexbuffer = NULL;
8461 rsurface.batchvertex3f_bufferoffset = 0;
8462 rsurface.batchsvector3f = NULL;
8463 rsurface.batchsvector3f_vertexbuffer = NULL;
8464 rsurface.batchsvector3f_bufferoffset = 0;
8465 rsurface.batchtvector3f = NULL;
8466 rsurface.batchtvector3f_vertexbuffer = NULL;
8467 rsurface.batchtvector3f_bufferoffset = 0;
8468 rsurface.batchnormal3f = NULL;
8469 rsurface.batchnormal3f_vertexbuffer = NULL;
8470 rsurface.batchnormal3f_bufferoffset = 0;
8471 rsurface.batchlightmapcolor4f = NULL;
8472 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8473 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8474 rsurface.batchtexcoordtexture2f = NULL;
8475 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8476 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8477 rsurface.batchtexcoordlightmap2f = NULL;
8478 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8479 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8480 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8481 rsurface.batchelement3i_indexbuffer = NULL;
8482 rsurface.batchelement3i_bufferoffset = 0;
8483 rsurface.batchelement3s = NULL;
8484 rsurface.batchelement3s_indexbuffer = NULL;
8485 rsurface.batchelement3s_bufferoffset = 0;
8486 // we'll only be setting up certain arrays as needed
8487 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8488 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8489 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8490 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8491 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8492 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8493 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8495 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8496 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8498 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8499 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8500 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8501 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8502 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8503 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8506 for (i = 0;i < texturenumsurfaces;i++)
8508 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8509 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8510 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8511 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8512 // copy only the data requested
8513 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8514 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8515 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8517 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8518 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8519 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8520 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8521 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8523 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8524 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8526 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8527 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8528 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8529 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8530 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8531 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8533 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8534 numvertices += surfacenumvertices;
8535 numtriangles += surfacenumtriangles;
8538 // generate a 16bit index array as well if possible
8539 // (in general, dynamic batches fit)
8540 if (numvertices <= 65536)
8542 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8543 for (i = 0;i < numtriangles*3;i++)
8544 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8547 // since we've copied everything, the batch now starts at 0
8548 rsurface.batchfirstvertex = 0;
8549 rsurface.batchnumvertices = batchnumvertices;
8550 rsurface.batchfirsttriangle = 0;
8551 rsurface.batchnumtriangles = batchnumtriangles;
8554 // q1bsp surfaces rendered in vertex color mode have to have colors
8555 // calculated based on lightstyles
8556 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8558 // generate color arrays for the surfaces in this list
8563 const unsigned char *lm;
8564 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8565 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8566 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8568 for (i = 0;i < texturenumsurfaces;i++)
8570 surface = texturesurfacelist[i];
8571 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8572 surfacenumvertices = surface->num_vertices;
8573 if (surface->lightmapinfo->samples)
8575 for (j = 0;j < surfacenumvertices;j++)
8577 lm = surface->lightmapinfo->samples + offsets[j];
8578 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8579 VectorScale(lm, scale, c);
8580 if (surface->lightmapinfo->styles[1] != 255)
8582 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8584 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8585 VectorMA(c, scale, lm, c);
8586 if (surface->lightmapinfo->styles[2] != 255)
8589 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8590 VectorMA(c, scale, lm, c);
8591 if (surface->lightmapinfo->styles[3] != 255)
8594 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8595 VectorMA(c, scale, lm, c);
8602 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);
8608 for (j = 0;j < surfacenumvertices;j++)
8610 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8617 // if vertices are deformed (sprite flares and things in maps, possibly
8618 // water waves, bulges and other deformations), modify the copied vertices
8620 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8622 switch (deform->deform)
8625 case Q3DEFORM_PROJECTIONSHADOW:
8626 case Q3DEFORM_TEXT0:
8627 case Q3DEFORM_TEXT1:
8628 case Q3DEFORM_TEXT2:
8629 case Q3DEFORM_TEXT3:
8630 case Q3DEFORM_TEXT4:
8631 case Q3DEFORM_TEXT5:
8632 case Q3DEFORM_TEXT6:
8633 case Q3DEFORM_TEXT7:
8636 case Q3DEFORM_AUTOSPRITE:
8637 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8638 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8639 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8640 VectorNormalize(newforward);
8641 VectorNormalize(newright);
8642 VectorNormalize(newup);
8643 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8644 // rsurface.batchvertex3f_vertexbuffer = NULL;
8645 // rsurface.batchvertex3f_bufferoffset = 0;
8646 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8647 // rsurface.batchsvector3f_vertexbuffer = NULL;
8648 // rsurface.batchsvector3f_bufferoffset = 0;
8649 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8650 // rsurface.batchtvector3f_vertexbuffer = NULL;
8651 // rsurface.batchtvector3f_bufferoffset = 0;
8652 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8653 // rsurface.batchnormal3f_vertexbuffer = NULL;
8654 // rsurface.batchnormal3f_bufferoffset = 0;
8655 // a single autosprite surface can contain multiple sprites...
8656 for (j = 0;j < batchnumvertices - 3;j += 4)
8658 VectorClear(center);
8659 for (i = 0;i < 4;i++)
8660 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8661 VectorScale(center, 0.25f, center);
8662 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8663 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8664 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8665 for (i = 0;i < 4;i++)
8667 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8668 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8671 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8672 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8673 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);
8675 case Q3DEFORM_AUTOSPRITE2:
8676 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8677 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8678 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8679 VectorNormalize(newforward);
8680 VectorNormalize(newright);
8681 VectorNormalize(newup);
8682 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8683 // rsurface.batchvertex3f_vertexbuffer = NULL;
8684 // rsurface.batchvertex3f_bufferoffset = 0;
8686 const float *v1, *v2;
8696 memset(shortest, 0, sizeof(shortest));
8697 // a single autosprite surface can contain multiple sprites...
8698 for (j = 0;j < batchnumvertices - 3;j += 4)
8700 VectorClear(center);
8701 for (i = 0;i < 4;i++)
8702 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8703 VectorScale(center, 0.25f, center);
8704 // find the two shortest edges, then use them to define the
8705 // axis vectors for rotating around the central axis
8706 for (i = 0;i < 6;i++)
8708 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8709 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8710 l = VectorDistance2(v1, v2);
8711 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8713 l += (1.0f / 1024.0f);
8714 if (shortest[0].length2 > l || i == 0)
8716 shortest[1] = shortest[0];
8717 shortest[0].length2 = l;
8718 shortest[0].v1 = v1;
8719 shortest[0].v2 = v2;
8721 else if (shortest[1].length2 > l || i == 1)
8723 shortest[1].length2 = l;
8724 shortest[1].v1 = v1;
8725 shortest[1].v2 = v2;
8728 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8729 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8730 // this calculates the right vector from the shortest edge
8731 // and the up vector from the edge midpoints
8732 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8733 VectorNormalize(right);
8734 VectorSubtract(end, start, up);
8735 VectorNormalize(up);
8736 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8737 VectorSubtract(rsurface.localvieworigin, center, forward);
8738 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8739 VectorNegate(forward, forward);
8740 VectorReflect(forward, 0, up, forward);
8741 VectorNormalize(forward);
8742 CrossProduct(up, forward, newright);
8743 VectorNormalize(newright);
8744 // rotate the quad around the up axis vector, this is made
8745 // especially easy by the fact we know the quad is flat,
8746 // so we only have to subtract the center position and
8747 // measure distance along the right vector, and then
8748 // multiply that by the newright vector and add back the
8750 // we also need to subtract the old position to undo the
8751 // displacement from the center, which we do with a
8752 // DotProduct, the subtraction/addition of center is also
8753 // optimized into DotProducts here
8754 l = DotProduct(right, center);
8755 for (i = 0;i < 4;i++)
8757 v1 = rsurface.batchvertex3f + 3*(j+i);
8758 f = DotProduct(right, v1) - l;
8759 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8763 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8765 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8766 // rsurface.batchnormal3f_vertexbuffer = NULL;
8767 // rsurface.batchnormal3f_bufferoffset = 0;
8768 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8770 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8772 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8773 // rsurface.batchsvector3f_vertexbuffer = NULL;
8774 // rsurface.batchsvector3f_bufferoffset = 0;
8775 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8776 // rsurface.batchtvector3f_vertexbuffer = NULL;
8777 // rsurface.batchtvector3f_bufferoffset = 0;
8778 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);
8781 case Q3DEFORM_NORMAL:
8782 // deform the normals to make reflections wavey
8783 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8784 rsurface.batchnormal3f_vertexbuffer = NULL;
8785 rsurface.batchnormal3f_bufferoffset = 0;
8786 for (j = 0;j < batchnumvertices;j++)
8789 float *normal = rsurface.batchnormal3f + 3*j;
8790 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8791 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8792 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]);
8793 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]);
8794 VectorNormalize(normal);
8796 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8798 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8799 // rsurface.batchsvector3f_vertexbuffer = NULL;
8800 // rsurface.batchsvector3f_bufferoffset = 0;
8801 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8802 // rsurface.batchtvector3f_vertexbuffer = NULL;
8803 // rsurface.batchtvector3f_bufferoffset = 0;
8804 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);
8808 // deform vertex array to make wavey water and flags and such
8809 waveparms[0] = deform->waveparms[0];
8810 waveparms[1] = deform->waveparms[1];
8811 waveparms[2] = deform->waveparms[2];
8812 waveparms[3] = deform->waveparms[3];
8813 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8814 break; // if wavefunc is a nop, don't make a dynamic vertex array
8815 // this is how a divisor of vertex influence on deformation
8816 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8817 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8818 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8819 // rsurface.batchvertex3f_vertexbuffer = NULL;
8820 // rsurface.batchvertex3f_bufferoffset = 0;
8821 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8822 // rsurface.batchnormal3f_vertexbuffer = NULL;
8823 // rsurface.batchnormal3f_bufferoffset = 0;
8824 for (j = 0;j < batchnumvertices;j++)
8826 // if the wavefunc depends on time, evaluate it per-vertex
8829 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8830 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8832 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8834 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8835 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8836 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8838 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8839 // rsurface.batchsvector3f_vertexbuffer = NULL;
8840 // rsurface.batchsvector3f_bufferoffset = 0;
8841 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8842 // rsurface.batchtvector3f_vertexbuffer = NULL;
8843 // rsurface.batchtvector3f_bufferoffset = 0;
8844 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);
8847 case Q3DEFORM_BULGE:
8848 // deform vertex array to make the surface have moving bulges
8849 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8850 // rsurface.batchvertex3f_vertexbuffer = NULL;
8851 // rsurface.batchvertex3f_bufferoffset = 0;
8852 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8853 // rsurface.batchnormal3f_vertexbuffer = NULL;
8854 // rsurface.batchnormal3f_bufferoffset = 0;
8855 for (j = 0;j < batchnumvertices;j++)
8857 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8858 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8860 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8861 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8862 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8864 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8865 // rsurface.batchsvector3f_vertexbuffer = NULL;
8866 // rsurface.batchsvector3f_bufferoffset = 0;
8867 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868 // rsurface.batchtvector3f_vertexbuffer = NULL;
8869 // rsurface.batchtvector3f_bufferoffset = 0;
8870 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);
8874 // deform vertex array
8875 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8876 break; // if wavefunc is a nop, don't make a dynamic vertex array
8877 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8878 VectorScale(deform->parms, scale, waveparms);
8879 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8880 // rsurface.batchvertex3f_vertexbuffer = NULL;
8881 // rsurface.batchvertex3f_bufferoffset = 0;
8882 for (j = 0;j < batchnumvertices;j++)
8883 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8888 // generate texcoords based on the chosen texcoord source
8889 switch(rsurface.texture->tcgen.tcgen)
8892 case Q3TCGEN_TEXTURE:
8894 case Q3TCGEN_LIGHTMAP:
8895 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8896 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8897 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8898 if (rsurface.batchtexcoordlightmap2f)
8899 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8901 case Q3TCGEN_VECTOR:
8902 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8903 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8904 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8905 for (j = 0;j < batchnumvertices;j++)
8907 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8908 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8911 case Q3TCGEN_ENVIRONMENT:
8912 // make environment reflections using a spheremap
8913 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8914 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8915 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8916 for (j = 0;j < batchnumvertices;j++)
8918 // identical to Q3A's method, but executed in worldspace so
8919 // carried models can be shiny too
8921 float viewer[3], d, reflected[3], worldreflected[3];
8923 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8924 // VectorNormalize(viewer);
8926 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8928 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8929 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8930 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8931 // note: this is proportinal to viewer, so we can normalize later
8933 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8934 VectorNormalize(worldreflected);
8936 // note: this sphere map only uses world x and z!
8937 // so positive and negative y will LOOK THE SAME.
8938 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8939 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8943 // the only tcmod that needs software vertex processing is turbulent, so
8944 // check for it here and apply the changes if needed
8945 // and we only support that as the first one
8946 // (handling a mixture of turbulent and other tcmods would be problematic
8947 // without punting it entirely to a software path)
8948 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8950 amplitude = rsurface.texture->tcmods[0].parms[1];
8951 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8952 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8953 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8954 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8955 for (j = 0;j < batchnumvertices;j++)
8957 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);
8958 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8962 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8964 // convert the modified arrays to vertex structs
8965 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8966 // rsurface.batchvertexmeshbuffer = NULL;
8967 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8968 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8969 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8970 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8971 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8972 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8973 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8975 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8977 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8978 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8981 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8982 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8983 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8984 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8985 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8986 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8987 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8988 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8989 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8993 void RSurf_DrawBatch(void)
8995 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8996 // through the pipeline, killing it earlier in the pipeline would have
8997 // per-surface overhead rather than per-batch overhead, so it's best to
8998 // reject it here, before it hits glDraw.
8999 if (rsurface.batchnumtriangles == 0)
9002 // batch debugging code
9003 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9009 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9010 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9013 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9015 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9017 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9018 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);
9025 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);
9028 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9030 // pick the closest matching water plane
9031 int planeindex, vertexindex, bestplaneindex = -1;
9035 r_waterstate_waterplane_t *p;
9036 qboolean prepared = false;
9038 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9040 if(p->camera_entity != rsurface.texture->camera_entity)
9045 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9047 if(rsurface.batchnumvertices == 0)
9050 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9052 Matrix4x4_Transform(&rsurface.matrix, v, vert);
9053 d += fabs(PlaneDiff(vert, &p->plane));
9055 if (bestd > d || bestplaneindex < 0)
9058 bestplaneindex = planeindex;
9061 return bestplaneindex;
9062 // NOTE: this MAY return a totally unrelated water plane; we can ignore
9063 // this situation though, as it might be better to render single larger
9064 // batches with useless stuff (backface culled for example) than to
9065 // render multiple smaller batches
9068 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9071 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9072 rsurface.passcolor4f_vertexbuffer = 0;
9073 rsurface.passcolor4f_bufferoffset = 0;
9074 for (i = 0;i < rsurface.batchnumvertices;i++)
9075 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9078 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9085 if (rsurface.passcolor4f)
9087 // generate color arrays
9088 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9089 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9090 rsurface.passcolor4f_vertexbuffer = 0;
9091 rsurface.passcolor4f_bufferoffset = 0;
9092 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)
9094 f = RSurf_FogVertex(v);
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9108 f = RSurf_FogVertex(v);
9117 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9124 if (!rsurface.passcolor4f)
9126 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9127 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9128 rsurface.passcolor4f_vertexbuffer = 0;
9129 rsurface.passcolor4f_bufferoffset = 0;
9130 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)
9132 f = RSurf_FogVertex(v);
9133 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9134 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9135 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9140 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9145 if (!rsurface.passcolor4f)
9147 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9148 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9149 rsurface.passcolor4f_vertexbuffer = 0;
9150 rsurface.passcolor4f_bufferoffset = 0;
9151 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9160 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9165 if (!rsurface.passcolor4f)
9167 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9168 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9169 rsurface.passcolor4f_vertexbuffer = 0;
9170 rsurface.passcolor4f_bufferoffset = 0;
9171 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9173 c2[0] = c[0] + r_refdef.scene.ambient;
9174 c2[1] = c[1] + r_refdef.scene.ambient;
9175 c2[2] = c[2] + r_refdef.scene.ambient;
9180 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9183 rsurface.passcolor4f = NULL;
9184 rsurface.passcolor4f_vertexbuffer = 0;
9185 rsurface.passcolor4f_bufferoffset = 0;
9186 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9187 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9188 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9189 GL_Color(r, g, b, a);
9190 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9194 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9196 // TODO: optimize applyfog && applycolor case
9197 // just apply fog if necessary, and tint the fog color array if necessary
9198 rsurface.passcolor4f = NULL;
9199 rsurface.passcolor4f_vertexbuffer = 0;
9200 rsurface.passcolor4f_bufferoffset = 0;
9201 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9202 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9203 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9204 GL_Color(r, g, b, a);
9208 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9211 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9212 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9213 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9214 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9215 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9216 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9217 GL_Color(r, g, b, a);
9221 static void RSurf_DrawBatch_GL11_ClampColor(void)
9226 if (!rsurface.passcolor4f)
9228 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9230 c2[0] = bound(0.0f, c1[0], 1.0f);
9231 c2[1] = bound(0.0f, c1[1], 1.0f);
9232 c2[2] = bound(0.0f, c1[2], 1.0f);
9233 c2[3] = bound(0.0f, c1[3], 1.0f);
9237 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9247 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9248 rsurface.passcolor4f_vertexbuffer = 0;
9249 rsurface.passcolor4f_bufferoffset = 0;
9250 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)
9252 f = -DotProduct(r_refdef.view.forward, n);
9254 f = f * 0.85 + 0.15; // work around so stuff won't get black
9255 f *= r_refdef.lightmapintensity;
9256 Vector4Set(c, f, f, f, 1);
9260 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9262 RSurf_DrawBatch_GL11_ApplyFakeLight();
9263 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9264 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9265 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9266 GL_Color(r, g, b, a);
9270 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9278 vec3_t ambientcolor;
9279 vec3_t diffusecolor;
9283 VectorCopy(rsurface.modellight_lightdir, lightdir);
9284 f = 0.5f * r_refdef.lightmapintensity;
9285 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9286 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9287 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9288 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9289 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9290 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9292 if (VectorLength2(diffusecolor) > 0)
9294 // q3-style directional shading
9295 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9296 rsurface.passcolor4f_vertexbuffer = 0;
9297 rsurface.passcolor4f_bufferoffset = 0;
9298 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)
9300 if ((f = DotProduct(n, lightdir)) > 0)
9301 VectorMA(ambientcolor, f, diffusecolor, c);
9303 VectorCopy(ambientcolor, c);
9310 *applycolor = false;
9314 *r = ambientcolor[0];
9315 *g = ambientcolor[1];
9316 *b = ambientcolor[2];
9317 rsurface.passcolor4f = NULL;
9318 rsurface.passcolor4f_vertexbuffer = 0;
9319 rsurface.passcolor4f_bufferoffset = 0;
9323 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9325 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9326 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9327 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9328 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9329 GL_Color(r, g, b, a);
9333 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9341 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9342 rsurface.passcolor4f_vertexbuffer = 0;
9343 rsurface.passcolor4f_bufferoffset = 0;
9345 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9347 f = 1 - RSurf_FogVertex(v);
9355 void RSurf_SetupDepthAndCulling(void)
9357 // submodels are biased to avoid z-fighting with world surfaces that they
9358 // may be exactly overlapping (avoids z-fighting artifacts on certain
9359 // doors and things in Quake maps)
9360 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9361 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9362 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9363 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9366 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9368 // transparent sky would be ridiculous
9369 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9371 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9372 skyrenderlater = true;
9373 RSurf_SetupDepthAndCulling();
9375 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9376 // skymasking on them, and Quake3 never did sky masking (unlike
9377 // software Quake and software Quake2), so disable the sky masking
9378 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9379 // and skymasking also looks very bad when noclipping outside the
9380 // level, so don't use it then either.
9381 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9383 R_Mesh_ResetTextureState();
9384 if (skyrendermasked)
9386 R_SetupShader_DepthOrShadow();
9387 // depth-only (masking)
9388 GL_ColorMask(0,0,0,0);
9389 // just to make sure that braindead drivers don't draw
9390 // anything despite that colormask...
9391 GL_BlendFunc(GL_ZERO, GL_ONE);
9392 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9393 if (rsurface.batchvertex3fbuffer)
9394 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9396 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9400 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9402 GL_BlendFunc(GL_ONE, GL_ZERO);
9403 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9404 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9405 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9408 if (skyrendermasked)
9409 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9411 R_Mesh_ResetTextureState();
9412 GL_Color(1, 1, 1, 1);
9415 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9416 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9417 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9419 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9423 // render screenspace normalmap to texture
9425 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9430 // bind lightmap texture
9432 // water/refraction/reflection/camera surfaces have to be handled specially
9433 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9435 int start, end, startplaneindex;
9436 for (start = 0;start < texturenumsurfaces;start = end)
9438 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9439 if(startplaneindex < 0)
9441 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9442 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9446 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9448 // now that we have a batch using the same planeindex, render it
9449 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9451 // render water or distortion background
9453 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));
9455 // blend surface on top
9456 GL_DepthMask(false);
9457 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9460 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9462 // render surface with reflection texture as input
9463 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9464 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));
9471 // render surface batch normally
9472 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9473 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9477 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9479 // OpenGL 1.3 path - anything not completely ancient
9480 qboolean applycolor;
9483 const texturelayer_t *layer;
9484 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);
9485 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9487 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9490 int layertexrgbscale;
9491 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9493 if (layerindex == 0)
9497 GL_AlphaTest(false);
9498 GL_DepthFunc(GL_EQUAL);
9501 GL_DepthMask(layer->depthmask && writedepth);
9502 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9503 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9505 layertexrgbscale = 4;
9506 VectorScale(layer->color, 0.25f, layercolor);
9508 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9510 layertexrgbscale = 2;
9511 VectorScale(layer->color, 0.5f, layercolor);
9515 layertexrgbscale = 1;
9516 VectorScale(layer->color, 1.0f, layercolor);
9518 layercolor[3] = layer->color[3];
9519 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9520 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9521 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9522 switch (layer->type)
9524 case TEXTURELAYERTYPE_LITTEXTURE:
9525 // single-pass lightmapped texture with 2x rgbscale
9526 R_Mesh_TexBind(0, r_texture_white);
9527 R_Mesh_TexMatrix(0, NULL);
9528 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9529 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9530 R_Mesh_TexBind(1, layer->texture);
9531 R_Mesh_TexMatrix(1, &layer->texmatrix);
9532 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9533 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9534 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9535 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9536 else if (FAKELIGHT_ENABLED)
9537 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9538 else if (rsurface.uselightmaptexture)
9539 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9541 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9543 case TEXTURELAYERTYPE_TEXTURE:
9544 // singletexture unlit texture with transparency support
9545 R_Mesh_TexBind(0, layer->texture);
9546 R_Mesh_TexMatrix(0, &layer->texmatrix);
9547 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9548 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9549 R_Mesh_TexBind(1, 0);
9550 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9551 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9553 case TEXTURELAYERTYPE_FOG:
9554 // singletexture fogging
9557 R_Mesh_TexBind(0, layer->texture);
9558 R_Mesh_TexMatrix(0, &layer->texmatrix);
9559 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9560 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9564 R_Mesh_TexBind(0, 0);
9565 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9567 R_Mesh_TexBind(1, 0);
9568 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9569 // generate a color array for the fog pass
9570 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9571 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9575 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9578 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9580 GL_DepthFunc(GL_LEQUAL);
9581 GL_AlphaTest(false);
9585 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9587 // OpenGL 1.1 - crusty old voodoo path
9590 const texturelayer_t *layer;
9591 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);
9592 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9594 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9596 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9598 if (layerindex == 0)
9602 GL_AlphaTest(false);
9603 GL_DepthFunc(GL_EQUAL);
9606 GL_DepthMask(layer->depthmask && writedepth);
9607 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9608 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9609 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9610 switch (layer->type)
9612 case TEXTURELAYERTYPE_LITTEXTURE:
9613 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9615 // two-pass lit texture with 2x rgbscale
9616 // first the lightmap pass
9617 R_Mesh_TexBind(0, r_texture_white);
9618 R_Mesh_TexMatrix(0, NULL);
9619 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9620 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9621 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9622 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9623 else if (FAKELIGHT_ENABLED)
9624 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9625 else if (rsurface.uselightmaptexture)
9626 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9628 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9629 // then apply the texture to it
9630 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9631 R_Mesh_TexBind(0, layer->texture);
9632 R_Mesh_TexMatrix(0, &layer->texmatrix);
9633 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9634 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9635 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);
9639 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9640 R_Mesh_TexBind(0, layer->texture);
9641 R_Mesh_TexMatrix(0, &layer->texmatrix);
9642 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9643 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9644 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9645 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);
9647 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);
9650 case TEXTURELAYERTYPE_TEXTURE:
9651 // singletexture unlit texture with transparency support
9652 R_Mesh_TexBind(0, layer->texture);
9653 R_Mesh_TexMatrix(0, &layer->texmatrix);
9654 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9655 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9656 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);
9658 case TEXTURELAYERTYPE_FOG:
9659 // singletexture fogging
9662 R_Mesh_TexBind(0, layer->texture);
9663 R_Mesh_TexMatrix(0, &layer->texmatrix);
9664 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9665 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9669 R_Mesh_TexBind(0, 0);
9670 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9672 // generate a color array for the fog pass
9673 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9674 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9678 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9681 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9683 GL_DepthFunc(GL_LEQUAL);
9684 GL_AlphaTest(false);
9688 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9692 r_vertexgeneric_t *batchvertex;
9695 // R_Mesh_ResetTextureState();
9696 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9698 if(rsurface.texture && rsurface.texture->currentskinframe)
9700 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9701 c[3] *= rsurface.texture->currentalpha;
9711 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9713 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9714 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9715 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9718 // brighten it up (as texture value 127 means "unlit")
9719 c[0] *= 2 * r_refdef.view.colorscale;
9720 c[1] *= 2 * r_refdef.view.colorscale;
9721 c[2] *= 2 * r_refdef.view.colorscale;
9723 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9724 c[3] *= r_wateralpha.value;
9726 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9728 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9729 GL_DepthMask(false);
9731 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9733 GL_BlendFunc(GL_ONE, GL_ONE);
9734 GL_DepthMask(false);
9736 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9738 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9739 GL_DepthMask(false);
9741 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9743 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9744 GL_DepthMask(false);
9748 GL_BlendFunc(GL_ONE, GL_ZERO);
9749 GL_DepthMask(writedepth);
9752 if (r_showsurfaces.integer == 3)
9754 rsurface.passcolor4f = NULL;
9756 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9758 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9760 rsurface.passcolor4f = NULL;
9761 rsurface.passcolor4f_vertexbuffer = 0;
9762 rsurface.passcolor4f_bufferoffset = 0;
9764 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9766 qboolean applycolor = true;
9769 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9771 r_refdef.lightmapintensity = 1;
9772 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9773 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9775 else if (FAKELIGHT_ENABLED)
9777 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9779 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9780 RSurf_DrawBatch_GL11_ApplyFakeLight();
9781 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9785 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9787 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9788 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9789 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9792 if(!rsurface.passcolor4f)
9793 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9795 RSurf_DrawBatch_GL11_ApplyAmbient();
9796 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9797 if(r_refdef.fogenabled)
9798 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9799 RSurf_DrawBatch_GL11_ClampColor();
9801 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9802 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9805 else if (!r_refdef.view.showdebug)
9807 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9809 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9811 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9812 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9814 R_Mesh_PrepareVertices_Generic_Unlock();
9817 else if (r_showsurfaces.integer == 4)
9819 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9820 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9821 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9823 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9824 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9825 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9827 R_Mesh_PrepareVertices_Generic_Unlock();
9830 else if (r_showsurfaces.integer == 2)
9833 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9834 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9835 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9837 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9838 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9839 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9840 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9841 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9842 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9843 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9845 R_Mesh_PrepareVertices_Generic_Unlock();
9846 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9850 int texturesurfaceindex;
9852 const msurface_t *surface;
9853 float surfacecolor4f[4];
9854 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9855 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9857 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9859 surface = texturesurfacelist[texturesurfaceindex];
9860 k = (int)(((size_t)surface) / sizeof(msurface_t));
9861 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9862 for (j = 0;j < surface->num_vertices;j++)
9864 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9865 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9869 R_Mesh_PrepareVertices_Generic_Unlock();
9874 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9877 RSurf_SetupDepthAndCulling();
9878 if (r_showsurfaces.integer)
9880 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9883 switch (vid.renderpath)
9885 case RENDERPATH_GL20:
9886 case RENDERPATH_D3D9:
9887 case RENDERPATH_D3D10:
9888 case RENDERPATH_D3D11:
9889 case RENDERPATH_SOFT:
9890 case RENDERPATH_GLES2:
9891 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9893 case RENDERPATH_GL13:
9894 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9896 case RENDERPATH_GL11:
9897 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9903 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9906 RSurf_SetupDepthAndCulling();
9907 if (r_showsurfaces.integer)
9909 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9912 switch (vid.renderpath)
9914 case RENDERPATH_GL20:
9915 case RENDERPATH_D3D9:
9916 case RENDERPATH_D3D10:
9917 case RENDERPATH_D3D11:
9918 case RENDERPATH_SOFT:
9919 case RENDERPATH_GLES2:
9920 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9922 case RENDERPATH_GL13:
9923 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9925 case RENDERPATH_GL11:
9926 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9932 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9935 int texturenumsurfaces, endsurface;
9937 const msurface_t *surface;
9938 #define MAXBATCH_TRANSPARENTSURFACES 256
9939 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9941 // if the model is static it doesn't matter what value we give for
9942 // wantnormals and wanttangents, so this logic uses only rules applicable
9943 // to a model, knowing that they are meaningless otherwise
9944 if (ent == r_refdef.scene.worldentity)
9945 RSurf_ActiveWorldEntity();
9946 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9947 RSurf_ActiveModelEntity(ent, false, false, false);
9950 switch (vid.renderpath)
9952 case RENDERPATH_GL20:
9953 case RENDERPATH_D3D9:
9954 case RENDERPATH_D3D10:
9955 case RENDERPATH_D3D11:
9956 case RENDERPATH_SOFT:
9957 case RENDERPATH_GLES2:
9958 RSurf_ActiveModelEntity(ent, true, true, false);
9960 case RENDERPATH_GL13:
9961 case RENDERPATH_GL11:
9962 RSurf_ActiveModelEntity(ent, true, false, false);
9967 if (r_transparentdepthmasking.integer)
9969 qboolean setup = false;
9970 for (i = 0;i < numsurfaces;i = j)
9973 surface = rsurface.modelsurfaces + surfacelist[i];
9974 texture = surface->texture;
9975 rsurface.texture = R_GetCurrentTexture(texture);
9976 rsurface.lightmaptexture = NULL;
9977 rsurface.deluxemaptexture = NULL;
9978 rsurface.uselightmaptexture = false;
9979 // scan ahead until we find a different texture
9980 endsurface = min(i + 1024, numsurfaces);
9981 texturenumsurfaces = 0;
9982 texturesurfacelist[texturenumsurfaces++] = surface;
9983 for (;j < endsurface;j++)
9985 surface = rsurface.modelsurfaces + surfacelist[j];
9986 if (texture != surface->texture)
9988 texturesurfacelist[texturenumsurfaces++] = surface;
9990 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9992 // render the range of surfaces as depth
9996 GL_ColorMask(0,0,0,0);
9999 GL_BlendFunc(GL_ONE, GL_ZERO);
10000 GL_DepthMask(true);
10001 // R_Mesh_ResetTextureState();
10002 R_SetupShader_DepthOrShadow();
10004 RSurf_SetupDepthAndCulling();
10005 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10006 if (rsurface.batchvertex3fbuffer)
10007 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10009 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10013 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10016 for (i = 0;i < numsurfaces;i = j)
10019 surface = rsurface.modelsurfaces + surfacelist[i];
10020 texture = surface->texture;
10021 rsurface.texture = R_GetCurrentTexture(texture);
10022 // scan ahead until we find a different texture
10023 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
10024 texturenumsurfaces = 0;
10025 texturesurfacelist[texturenumsurfaces++] = surface;
10026 if(FAKELIGHT_ENABLED)
10028 rsurface.lightmaptexture = NULL;
10029 rsurface.deluxemaptexture = NULL;
10030 rsurface.uselightmaptexture = false;
10031 for (;j < endsurface;j++)
10033 surface = rsurface.modelsurfaces + surfacelist[j];
10034 if (texture != surface->texture)
10036 texturesurfacelist[texturenumsurfaces++] = surface;
10041 rsurface.lightmaptexture = surface->lightmaptexture;
10042 rsurface.deluxemaptexture = surface->deluxemaptexture;
10043 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10044 for (;j < endsurface;j++)
10046 surface = rsurface.modelsurfaces + surfacelist[j];
10047 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10049 texturesurfacelist[texturenumsurfaces++] = surface;
10052 // render the range of surfaces
10053 if (ent == r_refdef.scene.worldentity)
10054 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10056 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10058 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10061 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10063 // transparent surfaces get pushed off into the transparent queue
10064 int surfacelistindex;
10065 const msurface_t *surface;
10066 vec3_t tempcenter, center;
10067 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10069 surface = texturesurfacelist[surfacelistindex];
10070 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10071 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10072 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10073 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10074 if (queueentity->transparent_offset) // transparent offset
10076 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10077 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10078 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10080 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10084 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10086 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10088 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10090 RSurf_SetupDepthAndCulling();
10091 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10092 if (rsurface.batchvertex3fbuffer)
10093 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10095 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10099 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10101 const entity_render_t *queueentity = r_refdef.scene.worldentity;
10104 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10107 if (!rsurface.texture->currentnumlayers)
10109 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10110 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10112 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10114 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10115 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10116 else if (!rsurface.texture->currentnumlayers)
10118 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10120 // in the deferred case, transparent surfaces were queued during prepass
10121 if (!r_shadow_usingdeferredprepass)
10122 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10126 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10127 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10132 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10135 texture_t *texture;
10136 R_FrameData_SetMark();
10137 // break the surface list down into batches by texture and use of lightmapping
10138 for (i = 0;i < numsurfaces;i = j)
10141 // texture is the base texture pointer, rsurface.texture is the
10142 // current frame/skin the texture is directing us to use (for example
10143 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10144 // use skin 1 instead)
10145 texture = surfacelist[i]->texture;
10146 rsurface.texture = R_GetCurrentTexture(texture);
10147 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10149 // if this texture is not the kind we want, skip ahead to the next one
10150 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10154 if(FAKELIGHT_ENABLED || depthonly || prepass)
10156 rsurface.lightmaptexture = NULL;
10157 rsurface.deluxemaptexture = NULL;
10158 rsurface.uselightmaptexture = false;
10159 // simply scan ahead until we find a different texture or lightmap state
10160 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10165 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10166 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10167 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10168 // simply scan ahead until we find a different texture or lightmap state
10169 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10172 // render the range of surfaces
10173 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10175 R_FrameData_ReturnToMark();
10178 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10182 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10185 if (!rsurface.texture->currentnumlayers)
10187 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10188 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10190 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10192 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10193 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10194 else if (!rsurface.texture->currentnumlayers)
10196 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10198 // in the deferred case, transparent surfaces were queued during prepass
10199 if (!r_shadow_usingdeferredprepass)
10200 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10204 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10205 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10210 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10213 texture_t *texture;
10214 R_FrameData_SetMark();
10215 // break the surface list down into batches by texture and use of lightmapping
10216 for (i = 0;i < numsurfaces;i = j)
10219 // texture is the base texture pointer, rsurface.texture is the
10220 // current frame/skin the texture is directing us to use (for example
10221 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10222 // use skin 1 instead)
10223 texture = surfacelist[i]->texture;
10224 rsurface.texture = R_GetCurrentTexture(texture);
10225 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10227 // if this texture is not the kind we want, skip ahead to the next one
10228 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10232 if(FAKELIGHT_ENABLED || depthonly || prepass)
10234 rsurface.lightmaptexture = NULL;
10235 rsurface.deluxemaptexture = NULL;
10236 rsurface.uselightmaptexture = false;
10237 // simply scan ahead until we find a different texture or lightmap state
10238 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10243 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10244 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10245 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10246 // simply scan ahead until we find a different texture or lightmap state
10247 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10250 // render the range of surfaces
10251 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10253 R_FrameData_ReturnToMark();
10256 float locboxvertex3f[6*4*3] =
10258 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10259 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10260 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10261 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10262 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10263 1,0,0, 0,0,0, 0,1,0, 1,1,0
10266 unsigned short locboxelements[6*2*3] =
10271 12,13,14, 12,14,15,
10272 16,17,18, 16,18,19,
10276 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10279 cl_locnode_t *loc = (cl_locnode_t *)ent;
10281 float vertex3f[6*4*3];
10283 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10284 GL_DepthMask(false);
10285 GL_DepthRange(0, 1);
10286 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10287 GL_DepthTest(true);
10288 GL_CullFace(GL_NONE);
10289 R_EntityMatrix(&identitymatrix);
10291 // R_Mesh_ResetTextureState();
10293 i = surfacelist[0];
10294 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10295 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10296 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10297 surfacelist[0] < 0 ? 0.5f : 0.125f);
10299 if (VectorCompare(loc->mins, loc->maxs))
10301 VectorSet(size, 2, 2, 2);
10302 VectorMA(loc->mins, -0.5f, size, mins);
10306 VectorCopy(loc->mins, mins);
10307 VectorSubtract(loc->maxs, loc->mins, size);
10310 for (i = 0;i < 6*4*3;)
10311 for (j = 0;j < 3;j++, i++)
10312 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10314 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10315 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10316 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10319 void R_DrawLocs(void)
10322 cl_locnode_t *loc, *nearestloc;
10324 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10325 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10327 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10328 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10332 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10334 if (decalsystem->decals)
10335 Mem_Free(decalsystem->decals);
10336 memset(decalsystem, 0, sizeof(*decalsystem));
10339 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)
10342 tridecal_t *decals;
10345 // expand or initialize the system
10346 if (decalsystem->maxdecals <= decalsystem->numdecals)
10348 decalsystem_t old = *decalsystem;
10349 qboolean useshortelements;
10350 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10351 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10352 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)));
10353 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10354 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10355 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10356 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10357 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10358 if (decalsystem->numdecals)
10359 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10361 Mem_Free(old.decals);
10362 for (i = 0;i < decalsystem->maxdecals*3;i++)
10363 decalsystem->element3i[i] = i;
10364 if (useshortelements)
10365 for (i = 0;i < decalsystem->maxdecals*3;i++)
10366 decalsystem->element3s[i] = i;
10369 // grab a decal and search for another free slot for the next one
10370 decals = decalsystem->decals;
10371 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10372 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10374 decalsystem->freedecal = i;
10375 if (decalsystem->numdecals <= i)
10376 decalsystem->numdecals = i + 1;
10378 // initialize the decal
10380 decal->triangleindex = triangleindex;
10381 decal->surfaceindex = surfaceindex;
10382 decal->decalsequence = decalsequence;
10383 decal->color4f[0][0] = c0[0];
10384 decal->color4f[0][1] = c0[1];
10385 decal->color4f[0][2] = c0[2];
10386 decal->color4f[0][3] = 1;
10387 decal->color4f[1][0] = c1[0];
10388 decal->color4f[1][1] = c1[1];
10389 decal->color4f[1][2] = c1[2];
10390 decal->color4f[1][3] = 1;
10391 decal->color4f[2][0] = c2[0];
10392 decal->color4f[2][1] = c2[1];
10393 decal->color4f[2][2] = c2[2];
10394 decal->color4f[2][3] = 1;
10395 decal->vertex3f[0][0] = v0[0];
10396 decal->vertex3f[0][1] = v0[1];
10397 decal->vertex3f[0][2] = v0[2];
10398 decal->vertex3f[1][0] = v1[0];
10399 decal->vertex3f[1][1] = v1[1];
10400 decal->vertex3f[1][2] = v1[2];
10401 decal->vertex3f[2][0] = v2[0];
10402 decal->vertex3f[2][1] = v2[1];
10403 decal->vertex3f[2][2] = v2[2];
10404 decal->texcoord2f[0][0] = t0[0];
10405 decal->texcoord2f[0][1] = t0[1];
10406 decal->texcoord2f[1][0] = t1[0];
10407 decal->texcoord2f[1][1] = t1[1];
10408 decal->texcoord2f[2][0] = t2[0];
10409 decal->texcoord2f[2][1] = t2[1];
10410 TriangleNormal(v0, v1, v2, decal->plane);
10411 VectorNormalize(decal->plane);
10412 decal->plane[3] = DotProduct(v0, decal->plane);
10415 extern cvar_t cl_decals_bias;
10416 extern cvar_t cl_decals_models;
10417 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10418 // baseparms, parms, temps
10419 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)
10424 const float *vertex3f;
10425 const float *normal3f;
10427 float points[2][9][3];
10434 e = rsurface.modelelement3i + 3*triangleindex;
10436 vertex3f = rsurface.modelvertex3f;
10437 normal3f = rsurface.modelnormal3f;
10441 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10443 index = 3*e[cornerindex];
10444 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10449 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10451 index = 3*e[cornerindex];
10452 VectorCopy(vertex3f + index, v[cornerindex]);
10457 //TriangleNormal(v[0], v[1], v[2], normal);
10458 //if (DotProduct(normal, localnormal) < 0.0f)
10460 // clip by each of the box planes formed from the projection matrix
10461 // if anything survives, we emit the decal
10462 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]);
10465 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]);
10468 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]);
10471 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]);
10474 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]);
10477 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]);
10480 // some part of the triangle survived, so we have to accept it...
10483 // dynamic always uses the original triangle
10485 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10487 index = 3*e[cornerindex];
10488 VectorCopy(vertex3f + index, v[cornerindex]);
10491 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10493 // convert vertex positions to texcoords
10494 Matrix4x4_Transform(projection, v[cornerindex], temp);
10495 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10496 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10497 // calculate distance fade from the projection origin
10498 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10499 f = bound(0.0f, f, 1.0f);
10500 c[cornerindex][0] = r * f;
10501 c[cornerindex][1] = g * f;
10502 c[cornerindex][2] = b * f;
10503 c[cornerindex][3] = 1.0f;
10504 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10507 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);
10509 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10510 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);
10512 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)
10514 matrix4x4_t projection;
10515 decalsystem_t *decalsystem;
10518 const msurface_t *surface;
10519 const msurface_t *surfaces;
10520 const int *surfacelist;
10521 const texture_t *texture;
10523 int numsurfacelist;
10524 int surfacelistindex;
10527 float localorigin[3];
10528 float localnormal[3];
10529 float localmins[3];
10530 float localmaxs[3];
10533 float planes[6][4];
10536 int bih_triangles_count;
10537 int bih_triangles[256];
10538 int bih_surfaces[256];
10540 decalsystem = &ent->decalsystem;
10541 model = ent->model;
10542 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10544 R_DecalSystem_Reset(&ent->decalsystem);
10548 if (!model->brush.data_leafs && !cl_decals_models.integer)
10550 if (decalsystem->model)
10551 R_DecalSystem_Reset(decalsystem);
10555 if (decalsystem->model != model)
10556 R_DecalSystem_Reset(decalsystem);
10557 decalsystem->model = model;
10559 RSurf_ActiveModelEntity(ent, true, false, false);
10561 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10562 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10563 VectorNormalize(localnormal);
10564 localsize = worldsize*rsurface.inversematrixscale;
10565 localmins[0] = localorigin[0] - localsize;
10566 localmins[1] = localorigin[1] - localsize;
10567 localmins[2] = localorigin[2] - localsize;
10568 localmaxs[0] = localorigin[0] + localsize;
10569 localmaxs[1] = localorigin[1] + localsize;
10570 localmaxs[2] = localorigin[2] + localsize;
10572 //VectorCopy(localnormal, planes[4]);
10573 //VectorVectors(planes[4], planes[2], planes[0]);
10574 AnglesFromVectors(angles, localnormal, NULL, false);
10575 AngleVectors(angles, planes[0], planes[2], planes[4]);
10576 VectorNegate(planes[0], planes[1]);
10577 VectorNegate(planes[2], planes[3]);
10578 VectorNegate(planes[4], planes[5]);
10579 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10580 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10581 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10582 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10583 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10584 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10589 matrix4x4_t forwardprojection;
10590 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10591 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10596 float projectionvector[4][3];
10597 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10598 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10599 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10600 projectionvector[0][0] = planes[0][0] * ilocalsize;
10601 projectionvector[0][1] = planes[1][0] * ilocalsize;
10602 projectionvector[0][2] = planes[2][0] * ilocalsize;
10603 projectionvector[1][0] = planes[0][1] * ilocalsize;
10604 projectionvector[1][1] = planes[1][1] * ilocalsize;
10605 projectionvector[1][2] = planes[2][1] * ilocalsize;
10606 projectionvector[2][0] = planes[0][2] * ilocalsize;
10607 projectionvector[2][1] = planes[1][2] * ilocalsize;
10608 projectionvector[2][2] = planes[2][2] * ilocalsize;
10609 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10610 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10611 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10612 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10616 dynamic = model->surfmesh.isanimated;
10617 numsurfacelist = model->nummodelsurfaces;
10618 surfacelist = model->sortedmodelsurfaces;
10619 surfaces = model->data_surfaces;
10622 bih_triangles_count = -1;
10625 if(model->render_bih.numleafs)
10626 bih = &model->render_bih;
10627 else if(model->collision_bih.numleafs)
10628 bih = &model->collision_bih;
10631 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10632 if(bih_triangles_count == 0)
10634 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10636 if(bih_triangles_count > 0)
10638 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10640 surfaceindex = bih_surfaces[triangleindex];
10641 surface = surfaces + surfaceindex;
10642 texture = surface->texture;
10643 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10645 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10647 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10652 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10654 surfaceindex = surfacelist[surfacelistindex];
10655 surface = surfaces + surfaceindex;
10656 // check cull box first because it rejects more than any other check
10657 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10659 // skip transparent surfaces
10660 texture = surface->texture;
10661 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10663 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10665 numtriangles = surface->num_triangles;
10666 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10667 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10672 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10673 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)
10675 int renderentityindex;
10676 float worldmins[3];
10677 float worldmaxs[3];
10678 entity_render_t *ent;
10680 if (!cl_decals_newsystem.integer)
10683 worldmins[0] = worldorigin[0] - worldsize;
10684 worldmins[1] = worldorigin[1] - worldsize;
10685 worldmins[2] = worldorigin[2] - worldsize;
10686 worldmaxs[0] = worldorigin[0] + worldsize;
10687 worldmaxs[1] = worldorigin[1] + worldsize;
10688 worldmaxs[2] = worldorigin[2] + worldsize;
10690 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10692 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10694 ent = r_refdef.scene.entities[renderentityindex];
10695 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10698 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10702 typedef struct r_decalsystem_splatqueue_s
10704 vec3_t worldorigin;
10705 vec3_t worldnormal;
10711 r_decalsystem_splatqueue_t;
10713 int r_decalsystem_numqueued = 0;
10714 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10716 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)
10718 r_decalsystem_splatqueue_t *queue;
10720 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10723 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10724 VectorCopy(worldorigin, queue->worldorigin);
10725 VectorCopy(worldnormal, queue->worldnormal);
10726 Vector4Set(queue->color, r, g, b, a);
10727 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10728 queue->worldsize = worldsize;
10729 queue->decalsequence = cl.decalsequence++;
10732 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10735 r_decalsystem_splatqueue_t *queue;
10737 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10738 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);
10739 r_decalsystem_numqueued = 0;
10742 extern cvar_t cl_decals_max;
10743 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10746 decalsystem_t *decalsystem = &ent->decalsystem;
10753 if (!decalsystem->numdecals)
10756 if (r_showsurfaces.integer)
10759 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10761 R_DecalSystem_Reset(decalsystem);
10765 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10766 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10768 if (decalsystem->lastupdatetime)
10769 frametime = (cl.time - decalsystem->lastupdatetime);
10772 decalsystem->lastupdatetime = cl.time;
10773 decal = decalsystem->decals;
10774 numdecals = decalsystem->numdecals;
10776 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10778 if (decal->color4f[0][3])
10780 decal->lived += frametime;
10781 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10783 memset(decal, 0, sizeof(*decal));
10784 if (decalsystem->freedecal > i)
10785 decalsystem->freedecal = i;
10789 decal = decalsystem->decals;
10790 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10793 // collapse the array by shuffling the tail decals into the gaps
10796 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10797 decalsystem->freedecal++;
10798 if (decalsystem->freedecal == numdecals)
10800 decal[decalsystem->freedecal] = decal[--numdecals];
10803 decalsystem->numdecals = numdecals;
10805 if (numdecals <= 0)
10807 // if there are no decals left, reset decalsystem
10808 R_DecalSystem_Reset(decalsystem);
10812 extern skinframe_t *decalskinframe;
10813 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10816 decalsystem_t *decalsystem = &ent->decalsystem;
10825 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10828 numdecals = decalsystem->numdecals;
10832 if (r_showsurfaces.integer)
10835 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10837 R_DecalSystem_Reset(decalsystem);
10841 // if the model is static it doesn't matter what value we give for
10842 // wantnormals and wanttangents, so this logic uses only rules applicable
10843 // to a model, knowing that they are meaningless otherwise
10844 if (ent == r_refdef.scene.worldentity)
10845 RSurf_ActiveWorldEntity();
10847 RSurf_ActiveModelEntity(ent, false, false, false);
10849 decalsystem->lastupdatetime = cl.time;
10850 decal = decalsystem->decals;
10852 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10854 // update vertex positions for animated models
10855 v3f = decalsystem->vertex3f;
10856 c4f = decalsystem->color4f;
10857 t2f = decalsystem->texcoord2f;
10858 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10860 if (!decal->color4f[0][3])
10863 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10867 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
10870 // update color values for fading decals
10871 if (decal->lived >= cl_decals_time.value)
10872 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10876 c4f[ 0] = decal->color4f[0][0] * alpha;
10877 c4f[ 1] = decal->color4f[0][1] * alpha;
10878 c4f[ 2] = decal->color4f[0][2] * alpha;
10880 c4f[ 4] = decal->color4f[1][0] * alpha;
10881 c4f[ 5] = decal->color4f[1][1] * alpha;
10882 c4f[ 6] = decal->color4f[1][2] * alpha;
10884 c4f[ 8] = decal->color4f[2][0] * alpha;
10885 c4f[ 9] = decal->color4f[2][1] * alpha;
10886 c4f[10] = decal->color4f[2][2] * alpha;
10889 t2f[0] = decal->texcoord2f[0][0];
10890 t2f[1] = decal->texcoord2f[0][1];
10891 t2f[2] = decal->texcoord2f[1][0];
10892 t2f[3] = decal->texcoord2f[1][1];
10893 t2f[4] = decal->texcoord2f[2][0];
10894 t2f[5] = decal->texcoord2f[2][1];
10896 // update vertex positions for animated models
10897 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10899 e = rsurface.modelelement3i + 3*decal->triangleindex;
10900 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10901 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10902 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10906 VectorCopy(decal->vertex3f[0], v3f);
10907 VectorCopy(decal->vertex3f[1], v3f + 3);
10908 VectorCopy(decal->vertex3f[2], v3f + 6);
10911 if (r_refdef.fogenabled)
10913 alpha = RSurf_FogVertex(v3f);
10914 VectorScale(c4f, alpha, c4f);
10915 alpha = RSurf_FogVertex(v3f + 3);
10916 VectorScale(c4f + 4, alpha, c4f + 4);
10917 alpha = RSurf_FogVertex(v3f + 6);
10918 VectorScale(c4f + 8, alpha, c4f + 8);
10929 r_refdef.stats.drawndecals += numtris;
10931 // now render the decals all at once
10932 // (this assumes they all use one particle font texture!)
10933 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);
10934 // R_Mesh_ResetTextureState();
10935 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10936 GL_DepthMask(false);
10937 GL_DepthRange(0, 1);
10938 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10939 GL_DepthTest(true);
10940 GL_CullFace(GL_NONE);
10941 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10942 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10943 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10947 static void R_DrawModelDecals(void)
10951 // fade faster when there are too many decals
10952 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10953 for (i = 0;i < r_refdef.scene.numentities;i++)
10954 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10956 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10957 for (i = 0;i < r_refdef.scene.numentities;i++)
10958 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10959 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10961 R_DecalSystem_ApplySplatEntitiesQueue();
10963 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10964 for (i = 0;i < r_refdef.scene.numentities;i++)
10965 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10967 r_refdef.stats.totaldecals += numdecals;
10969 if (r_showsurfaces.integer)
10972 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10974 for (i = 0;i < r_refdef.scene.numentities;i++)
10976 if (!r_refdef.viewcache.entityvisible[i])
10978 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10979 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10983 extern cvar_t mod_collision_bih;
10984 void R_DrawDebugModel(void)
10986 entity_render_t *ent = rsurface.entity;
10987 int i, j, k, l, flagsmask;
10988 const msurface_t *surface;
10989 dp_model_t *model = ent->model;
10992 if (r_showoverdraw.value > 0 && (sv.active || ent != r_refdef.scene.worldentity))
10994 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
10995 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10996 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10997 GL_DepthTest(false);
10998 GL_DepthMask(false);
10999 GL_DepthRange(0, 1);
11000 GL_BlendFunc(GL_ONE, GL_ONE);
11001 GL_CullFace(GL_NONE);
11002 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11004 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11006 rsurface.texture = R_GetCurrentTexture(surface->texture);
11007 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11009 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11010 if (!rsurface.texture->currentlayers->depthmask)
11011 GL_Color(c, 0, 0, 1.0f);
11012 else if (ent == r_refdef.scene.worldentity)
11013 GL_Color(c, c, c, 1.0f);
11015 GL_Color(0, c, 0, 1.0f);
11016 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11020 rsurface.texture = NULL;
11023 switch(vid.renderpath)
11025 case RENDERPATH_GL11:
11026 case RENDERPATH_GL13:
11027 case RENDERPATH_GL20:
11029 case RENDERPATH_D3D9:
11030 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11032 case RENDERPATH_D3D10:
11033 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11035 case RENDERPATH_D3D11:
11036 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11038 case RENDERPATH_SOFT:
11039 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11041 case RENDERPATH_GLES2:
11042 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
11046 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11048 // R_Mesh_ResetTextureState();
11049 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11050 GL_DepthRange(0, 1);
11051 GL_DepthTest(!r_showdisabledepthtest.integer);
11052 GL_DepthMask(false);
11053 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11055 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11059 qboolean cullbox = ent == r_refdef.scene.worldentity;
11060 const q3mbrush_t *brush;
11061 const bih_t *bih = &model->collision_bih;
11062 const bih_leaf_t *bihleaf;
11063 float vertex3f[3][3];
11064 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11066 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11068 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11070 switch (bihleaf->type)
11073 brush = model->brush.data_brushes + bihleaf->itemindex;
11074 if (brush->colbrushf && brush->colbrushf->numtriangles)
11076 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);
11077 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11078 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11081 case BIH_COLLISIONTRIANGLE:
11082 triangleindex = bihleaf->itemindex;
11083 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11084 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11085 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11086 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);
11087 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11088 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11090 case BIH_RENDERTRIANGLE:
11091 triangleindex = bihleaf->itemindex;
11092 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11093 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11094 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11095 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);
11096 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11097 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11103 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11105 if (r_showtris.integer || (r_shownormals.value != 0))
11107 if (r_showdisabledepthtest.integer)
11109 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11110 GL_DepthMask(false);
11114 GL_BlendFunc(GL_ONE, GL_ZERO);
11115 GL_DepthMask(true);
11117 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11119 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11121 rsurface.texture = R_GetCurrentTexture(surface->texture);
11122 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11124 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11125 if (r_showtris.value > 0)
11127 if (!rsurface.texture->currentlayers->depthmask)
11128 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11129 else if (ent == r_refdef.scene.worldentity)
11130 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11132 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11133 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11134 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
11136 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
11139 if (r_shownormals.value < 0)
11141 qglBegin(GL_LINES);
11142 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11144 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11145 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11146 qglVertex3f(v[0], v[1], v[2]);
11147 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11148 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11149 qglVertex3f(v[0], v[1], v[2]);
11154 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11156 qglBegin(GL_LINES);
11157 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11159 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11160 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11161 qglVertex3f(v[0], v[1], v[2]);
11162 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11163 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11164 qglVertex3f(v[0], v[1], v[2]);
11168 qglBegin(GL_LINES);
11169 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11171 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11172 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11173 qglVertex3f(v[0], v[1], v[2]);
11174 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11175 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11176 qglVertex3f(v[0], v[1], v[2]);
11180 qglBegin(GL_LINES);
11181 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11183 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11184 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11185 qglVertex3f(v[0], v[1], v[2]);
11186 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11187 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11188 qglVertex3f(v[0], v[1], v[2]);
11195 rsurface.texture = NULL;
11199 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11200 int r_maxsurfacelist = 0;
11201 const msurface_t **r_surfacelist = NULL;
11202 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11204 int i, j, endj, flagsmask;
11205 dp_model_t *model = r_refdef.scene.worldmodel;
11206 msurface_t *surfaces;
11207 unsigned char *update;
11208 int numsurfacelist = 0;
11212 if (r_maxsurfacelist < model->num_surfaces)
11214 r_maxsurfacelist = model->num_surfaces;
11216 Mem_Free((msurface_t**)r_surfacelist);
11217 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11220 RSurf_ActiveWorldEntity();
11222 surfaces = model->data_surfaces;
11223 update = model->brushq1.lightmapupdateflags;
11225 // update light styles on this submodel
11226 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11228 model_brush_lightstyleinfo_t *style;
11229 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11231 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11233 int *list = style->surfacelist;
11234 style->value = r_refdef.scene.lightstylevalue[style->style];
11235 for (j = 0;j < style->numsurfaces;j++)
11236 update[list[j]] = true;
11241 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11245 R_DrawDebugModel();
11246 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11250 rsurface.lightmaptexture = NULL;
11251 rsurface.deluxemaptexture = NULL;
11252 rsurface.uselightmaptexture = false;
11253 rsurface.texture = NULL;
11254 rsurface.rtlight = NULL;
11255 numsurfacelist = 0;
11256 // add visible surfaces to draw list
11257 for (i = 0;i < model->nummodelsurfaces;i++)
11259 j = model->sortedmodelsurfaces[i];
11260 if (r_refdef.viewcache.world_surfacevisible[j])
11261 r_surfacelist[numsurfacelist++] = surfaces + j;
11263 // update lightmaps if needed
11264 if (model->brushq1.firstrender)
11266 model->brushq1.firstrender = false;
11267 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11269 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11273 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11274 if (r_refdef.viewcache.world_surfacevisible[j])
11276 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11278 // don't do anything if there were no surfaces
11279 if (!numsurfacelist)
11281 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11284 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11286 // add to stats if desired
11287 if (r_speeds.integer && !skysurfaces && !depthonly)
11289 r_refdef.stats.world_surfaces += numsurfacelist;
11290 for (j = 0;j < numsurfacelist;j++)
11291 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11294 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11297 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11299 int i, j, endj, flagsmask;
11300 dp_model_t *model = ent->model;
11301 msurface_t *surfaces;
11302 unsigned char *update;
11303 int numsurfacelist = 0;
11307 if (r_maxsurfacelist < model->num_surfaces)
11309 r_maxsurfacelist = model->num_surfaces;
11311 Mem_Free((msurface_t **)r_surfacelist);
11312 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11315 // if the model is static it doesn't matter what value we give for
11316 // wantnormals and wanttangents, so this logic uses only rules applicable
11317 // to a model, knowing that they are meaningless otherwise
11318 if (ent == r_refdef.scene.worldentity)
11319 RSurf_ActiveWorldEntity();
11320 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11321 RSurf_ActiveModelEntity(ent, false, false, false);
11323 RSurf_ActiveModelEntity(ent, true, true, true);
11324 else if (depthonly)
11326 switch (vid.renderpath)
11328 case RENDERPATH_GL20:
11329 case RENDERPATH_D3D9:
11330 case RENDERPATH_D3D10:
11331 case RENDERPATH_D3D11:
11332 case RENDERPATH_SOFT:
11333 case RENDERPATH_GLES2:
11334 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11336 case RENDERPATH_GL13:
11337 case RENDERPATH_GL11:
11338 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11344 switch (vid.renderpath)
11346 case RENDERPATH_GL20:
11347 case RENDERPATH_D3D9:
11348 case RENDERPATH_D3D10:
11349 case RENDERPATH_D3D11:
11350 case RENDERPATH_SOFT:
11351 case RENDERPATH_GLES2:
11352 RSurf_ActiveModelEntity(ent, true, true, false);
11354 case RENDERPATH_GL13:
11355 case RENDERPATH_GL11:
11356 RSurf_ActiveModelEntity(ent, true, false, false);
11361 surfaces = model->data_surfaces;
11362 update = model->brushq1.lightmapupdateflags;
11364 // update light styles
11365 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11367 model_brush_lightstyleinfo_t *style;
11368 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11370 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11372 int *list = style->surfacelist;
11373 style->value = r_refdef.scene.lightstylevalue[style->style];
11374 for (j = 0;j < style->numsurfaces;j++)
11375 update[list[j]] = true;
11380 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11384 R_DrawDebugModel();
11385 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11389 rsurface.lightmaptexture = NULL;
11390 rsurface.deluxemaptexture = NULL;
11391 rsurface.uselightmaptexture = false;
11392 rsurface.texture = NULL;
11393 rsurface.rtlight = NULL;
11394 numsurfacelist = 0;
11395 // add visible surfaces to draw list
11396 for (i = 0;i < model->nummodelsurfaces;i++)
11397 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11398 // don't do anything if there were no surfaces
11399 if (!numsurfacelist)
11401 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11404 // update lightmaps if needed
11408 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11413 R_BuildLightMap(ent, surfaces + j);
11418 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11420 R_BuildLightMap(ent, surfaces + j);
11421 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11423 // add to stats if desired
11424 if (r_speeds.integer && !skysurfaces && !depthonly)
11426 r_refdef.stats.entities_surfaces += numsurfacelist;
11427 for (j = 0;j < numsurfacelist;j++)
11428 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11431 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11434 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11436 static texture_t texture;
11437 static msurface_t surface;
11438 const msurface_t *surfacelist = &surface;
11440 // fake enough texture and surface state to render this geometry
11442 texture.update_lastrenderframe = -1; // regenerate this texture
11443 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11444 texture.currentskinframe = skinframe;
11445 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11446 texture.offsetmapping = OFFSETMAPPING_OFF;
11447 texture.offsetscale = 1;
11448 texture.specularscalemod = 1;
11449 texture.specularpowermod = 1;
11451 surface.texture = &texture;
11452 surface.num_triangles = numtriangles;
11453 surface.num_firsttriangle = firsttriangle;
11454 surface.num_vertices = numvertices;
11455 surface.num_firstvertex = firstvertex;
11458 rsurface.texture = R_GetCurrentTexture(surface.texture);
11459 rsurface.lightmaptexture = NULL;
11460 rsurface.deluxemaptexture = NULL;
11461 rsurface.uselightmaptexture = false;
11462 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11465 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)
11467 static msurface_t surface;
11468 const msurface_t *surfacelist = &surface;
11470 // fake enough texture and surface state to render this geometry
11471 surface.texture = texture;
11472 surface.num_triangles = numtriangles;
11473 surface.num_firsttriangle = firsttriangle;
11474 surface.num_vertices = numvertices;
11475 surface.num_firstvertex = firstvertex;
11478 rsurface.texture = R_GetCurrentTexture(surface.texture);
11479 rsurface.lightmaptexture = NULL;
11480 rsurface.deluxemaptexture = NULL;
11481 rsurface.uselightmaptexture = false;
11482 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);