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_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%, 10 = 100%)"};
74 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)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 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"};
78 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"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 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"};
81 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"};
82 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"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 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)"};
91 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)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 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."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 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."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 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"};
114 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"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 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"};
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
130 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)"};
131 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"};
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143 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)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 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)"};
146 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
147 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)"};
148 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
149 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
150 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)"};
151 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)"};
152 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)"};
153 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)"};
154 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)"};
155 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)"};
156 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)"};
157 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)"};
159 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)"};
160 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
161 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"};
162 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
163 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
164 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
166 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
167 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
168 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
169 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
171 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
172 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
173 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
174 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
175 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
176 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
177 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
179 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
180 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
181 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
182 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)"};
183 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
184 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
185 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
186 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
187 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
188 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
190 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"};
192 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"};
194 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
196 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
197 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"};
198 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
199 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
200 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
201 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
202 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)"};
203 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
204 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
206 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
207 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"};
209 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)"};
211 extern cvar_t v_glslgamma;
213 extern qboolean v_flipped_state;
215 static struct r_bloomstate_s
220 int bloomwidth, bloomheight;
222 int screentexturewidth, screentextureheight;
223 rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
225 int bloomtexturewidth, bloomtextureheight;
226 rtexture_t *texture_bloom;
228 // arrays for rendering the screen passes
229 float screentexcoord2f[8];
230 float bloomtexcoord2f[8];
231 float offsettexcoord2f[8];
233 r_viewport_t viewport;
237 r_waterstate_t r_waterstate;
239 /// shadow volume bsp struct with automatically growing nodes buffer
242 rtexture_t *r_texture_blanknormalmap;
243 rtexture_t *r_texture_white;
244 rtexture_t *r_texture_grey128;
245 rtexture_t *r_texture_black;
246 rtexture_t *r_texture_notexture;
247 rtexture_t *r_texture_whitecube;
248 rtexture_t *r_texture_normalizationcube;
249 rtexture_t *r_texture_fogattenuation;
250 rtexture_t *r_texture_fogheighttexture;
251 rtexture_t *r_texture_gammaramps;
252 unsigned int r_texture_gammaramps_serial;
253 //rtexture_t *r_texture_fogintensity;
254 rtexture_t *r_texture_reflectcube;
256 // TODO: hash lookups?
257 typedef struct cubemapinfo_s
264 int r_texture_numcubemaps;
265 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
267 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
268 unsigned int r_numqueries;
269 unsigned int r_maxqueries;
271 typedef struct r_qwskincache_s
273 char name[MAX_QPATH];
274 skinframe_t *skinframe;
278 static r_qwskincache_t *r_qwskincache;
279 static int r_qwskincache_size;
281 /// vertex coordinates for a quad that covers the screen exactly
282 extern const float r_screenvertex3f[12];
283 extern const float r_d3dscreenvertex3f[12];
284 const float r_screenvertex3f[12] =
291 const float r_d3dscreenvertex3f[12] =
299 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
302 for (i = 0;i < verts;i++)
313 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
316 for (i = 0;i < verts;i++)
326 // FIXME: move this to client?
329 if (gamemode == GAME_NEHAHRA)
331 Cvar_Set("gl_fogenable", "0");
332 Cvar_Set("gl_fogdensity", "0.2");
333 Cvar_Set("gl_fogred", "0.3");
334 Cvar_Set("gl_foggreen", "0.3");
335 Cvar_Set("gl_fogblue", "0.3");
337 r_refdef.fog_density = 0;
338 r_refdef.fog_red = 0;
339 r_refdef.fog_green = 0;
340 r_refdef.fog_blue = 0;
341 r_refdef.fog_alpha = 1;
342 r_refdef.fog_start = 0;
343 r_refdef.fog_end = 16384;
344 r_refdef.fog_height = 1<<30;
345 r_refdef.fog_fadedepth = 128;
346 memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
349 static void R_BuildBlankTextures(void)
351 unsigned char data[4];
352 data[2] = 128; // normal X
353 data[1] = 128; // normal Y
354 data[0] = 255; // normal Z
355 data[3] = 128; // height
356 r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361 r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366 r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 static void R_BuildNoTexture(void)
377 unsigned char pix[16][16][4];
378 // this makes a light grey/dark grey checkerboard texture
379 for (y = 0;y < 16;y++)
381 for (x = 0;x < 16;x++)
383 if ((y < 8) ^ (x < 8))
399 r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
402 static void R_BuildWhiteCube(void)
404 unsigned char data[6*1*1*4];
405 memset(data, 255, sizeof(data));
406 r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
409 static void R_BuildNormalizationCube(void)
413 vec_t s, t, intensity;
416 data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
417 for (side = 0;side < 6;side++)
419 for (y = 0;y < NORMSIZE;y++)
421 for (x = 0;x < NORMSIZE;x++)
423 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
459 intensity = 127.0f / sqrt(DotProduct(v, v));
460 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
461 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
462 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
463 data[((side*64+y)*64+x)*4+3] = 255;
467 r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
471 static void R_BuildFogTexture(void)
475 unsigned char data1[FOGWIDTH][4];
476 //unsigned char data2[FOGWIDTH][4];
479 r_refdef.fogmasktable_start = r_refdef.fog_start;
480 r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
481 r_refdef.fogmasktable_range = r_refdef.fogrange;
482 r_refdef.fogmasktable_density = r_refdef.fog_density;
484 r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
485 for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487 d = (x * r - r_refdef.fogmasktable_start);
488 if(developer_extra.integer)
489 Con_DPrintf("%f ", d);
491 if (r_fog_exp2.integer)
492 alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494 alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
495 if(developer_extra.integer)
496 Con_DPrintf(" : %f ", alpha);
497 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
498 if(developer_extra.integer)
499 Con_DPrintf(" = %f\n", alpha);
500 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
503 for (x = 0;x < FOGWIDTH;x++)
505 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
510 //data2[x][0] = 255 - b;
511 //data2[x][1] = 255 - b;
512 //data2[x][2] = 255 - b;
515 if (r_texture_fogattenuation)
517 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
522 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
523 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
527 static void R_BuildFogHeightTexture(void)
529 unsigned char *inpixels;
537 strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
538 if (r_refdef.fogheighttexturename[0])
539 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
542 r_refdef.fog_height_tablesize = 0;
543 if (r_texture_fogheighttexture)
544 R_FreeTexture(r_texture_fogheighttexture);
545 r_texture_fogheighttexture = NULL;
546 if (r_refdef.fog_height_table2d)
547 Mem_Free(r_refdef.fog_height_table2d);
548 r_refdef.fog_height_table2d = NULL;
549 if (r_refdef.fog_height_table1d)
550 Mem_Free(r_refdef.fog_height_table1d);
551 r_refdef.fog_height_table1d = NULL;
555 r_refdef.fog_height_tablesize = size;
556 r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
557 r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
558 memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560 // LordHavoc: now the magic - what is that table2d for? it is a cooked
561 // average fog color table accounting for every fog layer between a point
562 // and the camera. (Note: attenuation is handled separately!)
563 for (y = 0;y < size;y++)
565 for (x = 0;x < size;x++)
571 for (j = x;j <= y;j++)
573 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
579 for (j = x;j >= y;j--)
581 Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
586 r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
587 r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
588 r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
589 r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
592 r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
595 //=======================================================================================================================================================
597 static const char *builtinshaderstring =
598 #include "shader_glsl.h"
601 const char *builtinhlslshaderstring =
602 #include "shader_hlsl.h"
605 char *glslshaderstring = NULL;
606 char *hlslshaderstring = NULL;
608 //=======================================================================================================================================================
610 typedef struct shaderpermutationinfo_s
615 shaderpermutationinfo_t;
617 typedef struct shadermodeinfo_s
619 const char *vertexfilename;
620 const char *geometryfilename;
621 const char *fragmentfilename;
627 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
628 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {"#define USEDIFFUSE\n", " diffuse"},
631 {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
632 {"#define USEVIEWTINT\n", " viewtint"},
633 {"#define USECOLORMAPPING\n", " colormapping"},
634 {"#define USESATURATION\n", " saturation"},
635 {"#define USEFOGINSIDE\n", " foginside"},
636 {"#define USEFOGOUTSIDE\n", " fogoutside"},
637 {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
638 {"#define USEFOGALPHAHACK\n", " fogalphahack"},
639 {"#define USEGAMMARAMPS\n", " gammaramps"},
640 {"#define USECUBEFILTER\n", " cubefilter"},
641 {"#define USEGLOW\n", " glow"},
642 {"#define USEBLOOM\n", " bloom"},
643 {"#define USESPECULAR\n", " specular"},
644 {"#define USEPOSTPROCESSING\n", " postprocessing"},
645 {"#define USEREFLECTION\n", " reflection"},
646 {"#define USEOFFSETMAPPING\n", " offsetmapping"},
647 {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
648 {"#define USESHADOWMAP2D\n", " shadowmap2d"},
649 {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
650 {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
651 {"#define USESHADOWSAMPLER\n", " shadowsampler"},
652 {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
653 {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
654 {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
655 {"#define USEALPHAKILL\n", " alphakill"},
656 {"#define USEREFLECTCUBE\n", " reflectcube"},
657 {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
658 {"#define USEBOUNCEGRID\n", " bouncegrid"},
659 {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
662 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
663 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
666 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
667 {"glsl/default.glsl", NULL, NULL , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
668 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
669 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
670 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
671 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
672 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
673 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
674 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
675 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
676 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
677 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
678 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
679 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
680 {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
683 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
686 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
695 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
696 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
697 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
698 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
699 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
700 {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 struct r_glsl_permutation_s;
704 typedef struct r_glsl_permutation_s
707 struct r_glsl_permutation_s *hashnext;
709 unsigned int permutation;
711 /// indicates if we have tried compiling this permutation already
713 /// 0 if compilation failed
715 // texture units assigned to each detected uniform
716 int tex_Texture_First;
717 int tex_Texture_Second;
718 int tex_Texture_GammaRamps;
719 int tex_Texture_Normal;
720 int tex_Texture_Color;
721 int tex_Texture_Gloss;
722 int tex_Texture_Glow;
723 int tex_Texture_SecondaryNormal;
724 int tex_Texture_SecondaryColor;
725 int tex_Texture_SecondaryGloss;
726 int tex_Texture_SecondaryGlow;
727 int tex_Texture_Pants;
728 int tex_Texture_Shirt;
729 int tex_Texture_FogHeightTexture;
730 int tex_Texture_FogMask;
731 int tex_Texture_Lightmap;
732 int tex_Texture_Deluxemap;
733 int tex_Texture_Attenuation;
734 int tex_Texture_Cube;
735 int tex_Texture_Refraction;
736 int tex_Texture_Reflection;
737 int tex_Texture_ShadowMap2D;
738 int tex_Texture_CubeProjection;
739 int tex_Texture_ScreenDepth;
740 int tex_Texture_ScreenNormalMap;
741 int tex_Texture_ScreenDiffuse;
742 int tex_Texture_ScreenSpecular;
743 int tex_Texture_ReflectMask;
744 int tex_Texture_ReflectCube;
745 int tex_Texture_BounceGrid;
746 /// locations of detected uniforms in program object, or -1 if not found
747 int loc_Texture_First;
748 int loc_Texture_Second;
749 int loc_Texture_GammaRamps;
750 int loc_Texture_Normal;
751 int loc_Texture_Color;
752 int loc_Texture_Gloss;
753 int loc_Texture_Glow;
754 int loc_Texture_SecondaryNormal;
755 int loc_Texture_SecondaryColor;
756 int loc_Texture_SecondaryGloss;
757 int loc_Texture_SecondaryGlow;
758 int loc_Texture_Pants;
759 int loc_Texture_Shirt;
760 int loc_Texture_FogHeightTexture;
761 int loc_Texture_FogMask;
762 int loc_Texture_Lightmap;
763 int loc_Texture_Deluxemap;
764 int loc_Texture_Attenuation;
765 int loc_Texture_Cube;
766 int loc_Texture_Refraction;
767 int loc_Texture_Reflection;
768 int loc_Texture_ShadowMap2D;
769 int loc_Texture_CubeProjection;
770 int loc_Texture_ScreenDepth;
771 int loc_Texture_ScreenNormalMap;
772 int loc_Texture_ScreenDiffuse;
773 int loc_Texture_ScreenSpecular;
774 int loc_Texture_ReflectMask;
775 int loc_Texture_ReflectCube;
776 int loc_Texture_BounceGrid;
778 int loc_BloomBlur_Parameters;
780 int loc_Color_Ambient;
781 int loc_Color_Diffuse;
782 int loc_Color_Specular;
786 int loc_DeferredColor_Ambient;
787 int loc_DeferredColor_Diffuse;
788 int loc_DeferredColor_Specular;
789 int loc_DeferredMod_Diffuse;
790 int loc_DeferredMod_Specular;
791 int loc_DistortScaleRefractReflect;
794 int loc_FogHeightFade;
796 int loc_FogPlaneViewDist;
797 int loc_FogRangeRecip;
800 int loc_LightPosition;
801 int loc_OffsetMapping_ScaleSteps;
803 int loc_ReflectColor;
804 int loc_ReflectFactor;
805 int loc_ReflectOffset;
806 int loc_RefractColor;
808 int loc_ScreenCenterRefractReflect;
809 int loc_ScreenScaleRefractReflect;
810 int loc_ScreenToDepth;
811 int loc_ShadowMap_Parameters;
812 int loc_ShadowMap_TextureScale;
813 int loc_SpecularPower;
818 int loc_ViewTintColor;
820 int loc_ModelToLight;
822 int loc_BackgroundTexMatrix;
823 int loc_ModelViewProjectionMatrix;
824 int loc_ModelViewMatrix;
825 int loc_PixelToScreenTexCoord;
826 int loc_ModelToReflectCube;
827 int loc_ShadowMapMatrix;
828 int loc_BloomColorSubtract;
829 int loc_NormalmapScrollBlend;
830 int loc_BounceGridMatrix;
831 int loc_BounceGridIntensity;
833 r_glsl_permutation_t;
835 #define SHADERPERMUTATION_HASHSIZE 256
838 // non-degradable "lightweight" shader parameters to keep the permutations simpler
839 // these can NOT degrade! only use for simple stuff
842 SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
843 SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
844 SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
845 SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
846 SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
847 SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5 ///< postprocess uservec4 is enabled
849 #define SHADERSTATICPARMS_COUNT 6
851 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
852 static int shaderstaticparms_count = 0;
854 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
855 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
856 qboolean R_CompileShader_CheckStaticParms(void)
858 static int r_compileshader_staticparms_save[1];
859 memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
860 memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
863 if (r_glsl_saturation_redcompensate.integer)
864 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
865 if (r_shadow_glossexact.integer)
866 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
867 if (r_glsl_postprocess.integer)
869 if (r_glsl_postprocess_uservec1_enable.integer)
870 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
871 if (r_glsl_postprocess_uservec2_enable.integer)
872 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
873 if (r_glsl_postprocess_uservec3_enable.integer)
874 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
875 if (r_glsl_postprocess_uservec4_enable.integer)
876 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
878 return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
881 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
882 if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
883 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
885 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
886 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
888 shaderstaticparms_count = 0;
891 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
892 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
893 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
894 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
895 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
896 R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
899 /// information about each possible shader permutation
900 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
901 /// currently selected permutation
902 r_glsl_permutation_t *r_glsl_permutation;
903 /// storage for permutations linked in the hash table
904 memexpandablearray_t r_glsl_permutationarray;
906 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
908 //unsigned int hashdepth = 0;
909 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
910 r_glsl_permutation_t *p;
911 for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
913 if (p->mode == mode && p->permutation == permutation)
915 //if (hashdepth > 10)
916 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
921 p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
923 p->permutation = permutation;
924 p->hashnext = r_glsl_permutationhash[mode][hashindex];
925 r_glsl_permutationhash[mode][hashindex] = p;
926 //if (hashdepth > 10)
927 // Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
931 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
934 if (!filename || !filename[0])
936 if (!strcmp(filename, "glsl/default.glsl"))
938 if (!glslshaderstring)
940 glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
941 if (glslshaderstring)
942 Con_DPrintf("Loading shaders from file %s...\n", filename);
944 glslshaderstring = (char *)builtinshaderstring;
946 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
947 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
950 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
953 if (printfromdisknotice)
954 Con_DPrintf("from disk %s... ", filename);
960 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
964 shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
965 char *vertexstring, *geometrystring, *fragmentstring;
966 char permutationname[256];
967 int vertstrings_count = 0;
968 int geomstrings_count = 0;
969 int fragstrings_count = 0;
970 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
971 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
972 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
979 permutationname[0] = 0;
980 vertexstring = R_GLSL_GetText(modeinfo->vertexfilename, true);
981 geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
982 fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
984 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
986 // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
987 if(vid.support.gl20shaders130)
989 vertstrings_list[vertstrings_count++] = "#version 130\n";
990 geomstrings_list[geomstrings_count++] = "#version 130\n";
991 fragstrings_list[fragstrings_count++] = "#version 130\n";
994 // the first pretext is which type of shader to compile as
995 // (later these will all be bound together as a program object)
996 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
997 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
998 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1000 // the second pretext is the mode (for example a light source)
1001 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1002 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1003 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1004 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1006 // now add all the permutation pretexts
1007 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1009 if (permutation & (1<<i))
1011 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1012 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1013 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1014 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1018 // keep line numbers correct
1019 vertstrings_list[vertstrings_count++] = "\n";
1020 geomstrings_list[geomstrings_count++] = "\n";
1021 fragstrings_list[fragstrings_count++] = "\n";
1026 R_CompileShader_AddStaticParms(mode, permutation);
1027 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1028 vertstrings_count += shaderstaticparms_count;
1029 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1030 geomstrings_count += shaderstaticparms_count;
1031 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1032 fragstrings_count += shaderstaticparms_count;
1034 // now append the shader text itself
1035 vertstrings_list[vertstrings_count++] = vertexstring;
1036 geomstrings_list[geomstrings_count++] = geometrystring;
1037 fragstrings_list[fragstrings_count++] = fragmentstring;
1039 // if any sources were NULL, clear the respective list
1041 vertstrings_count = 0;
1042 if (!geometrystring)
1043 geomstrings_count = 0;
1044 if (!fragmentstring)
1045 fragstrings_count = 0;
1047 // compile the shader program
1048 if (vertstrings_count + geomstrings_count + fragstrings_count)
1049 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1053 qglUseProgram(p->program);CHECKGLERROR
1054 // look up all the uniform variable names we care about, so we don't
1055 // have to look them up every time we set them
1057 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1058 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1059 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1060 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1061 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1062 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1063 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1064 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1065 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1066 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1067 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1068 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1069 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1070 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1071 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1072 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1073 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1074 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1075 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1076 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1077 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1078 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1079 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1080 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1081 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1082 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1083 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1084 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1085 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1086 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1087 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1088 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1089 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1090 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1091 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1092 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1093 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1094 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1095 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1096 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1097 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1098 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1099 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1100 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1101 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1102 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1103 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1104 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1105 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1106 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1107 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1108 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1109 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1110 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1111 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1112 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1113 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1114 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1115 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1116 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1117 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1118 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1119 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1120 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1121 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1122 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1123 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1124 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1125 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1126 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1127 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1128 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1129 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1130 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1131 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1132 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1133 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1134 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1135 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1136 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1137 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1138 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1139 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1140 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1141 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1142 // initialize the samplers to refer to the texture units we use
1143 p->tex_Texture_First = -1;
1144 p->tex_Texture_Second = -1;
1145 p->tex_Texture_GammaRamps = -1;
1146 p->tex_Texture_Normal = -1;
1147 p->tex_Texture_Color = -1;
1148 p->tex_Texture_Gloss = -1;
1149 p->tex_Texture_Glow = -1;
1150 p->tex_Texture_SecondaryNormal = -1;
1151 p->tex_Texture_SecondaryColor = -1;
1152 p->tex_Texture_SecondaryGloss = -1;
1153 p->tex_Texture_SecondaryGlow = -1;
1154 p->tex_Texture_Pants = -1;
1155 p->tex_Texture_Shirt = -1;
1156 p->tex_Texture_FogHeightTexture = -1;
1157 p->tex_Texture_FogMask = -1;
1158 p->tex_Texture_Lightmap = -1;
1159 p->tex_Texture_Deluxemap = -1;
1160 p->tex_Texture_Attenuation = -1;
1161 p->tex_Texture_Cube = -1;
1162 p->tex_Texture_Refraction = -1;
1163 p->tex_Texture_Reflection = -1;
1164 p->tex_Texture_ShadowMap2D = -1;
1165 p->tex_Texture_CubeProjection = -1;
1166 p->tex_Texture_ScreenDepth = -1;
1167 p->tex_Texture_ScreenNormalMap = -1;
1168 p->tex_Texture_ScreenDiffuse = -1;
1169 p->tex_Texture_ScreenSpecular = -1;
1170 p->tex_Texture_ReflectMask = -1;
1171 p->tex_Texture_ReflectCube = -1;
1172 p->tex_Texture_BounceGrid = -1;
1174 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1175 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1176 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1177 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1178 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1179 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1180 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1181 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1182 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1183 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1184 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1185 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1186 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1187 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1188 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1189 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1190 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1191 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1192 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1193 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1194 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1195 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1196 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1197 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1198 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1199 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1200 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1201 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1202 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1203 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1205 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1208 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1212 Mem_Free(vertexstring);
1214 Mem_Free(geometrystring);
1216 Mem_Free(fragmentstring);
1219 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1221 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1222 if (r_glsl_permutation != perm)
1224 r_glsl_permutation = perm;
1225 if (!r_glsl_permutation->program)
1227 if (!r_glsl_permutation->compiled)
1228 R_GLSL_CompilePermutation(perm, mode, permutation);
1229 if (!r_glsl_permutation->program)
1231 // remove features until we find a valid permutation
1233 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1235 // reduce i more quickly whenever it would not remove any bits
1236 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1237 if (!(permutation & j))
1240 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1241 if (!r_glsl_permutation->compiled)
1242 R_GLSL_CompilePermutation(perm, mode, permutation);
1243 if (r_glsl_permutation->program)
1246 if (i >= SHADERPERMUTATION_COUNT)
1248 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1249 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1250 qglUseProgram(0);CHECKGLERROR
1251 return; // no bit left to clear, entire mode is broken
1256 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1258 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1259 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1260 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1267 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1268 extern D3DCAPS9 vid_d3d9caps;
1271 struct r_hlsl_permutation_s;
1272 typedef struct r_hlsl_permutation_s
1274 /// hash lookup data
1275 struct r_hlsl_permutation_s *hashnext;
1277 unsigned int permutation;
1279 /// indicates if we have tried compiling this permutation already
1281 /// NULL if compilation failed
1282 IDirect3DVertexShader9 *vertexshader;
1283 IDirect3DPixelShader9 *pixelshader;
1285 r_hlsl_permutation_t;
1287 typedef enum D3DVSREGISTER_e
1289 D3DVSREGISTER_TexMatrix = 0, // float4x4
1290 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1291 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1292 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1293 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1294 D3DVSREGISTER_ModelToLight = 20, // float4x4
1295 D3DVSREGISTER_EyePosition = 24,
1296 D3DVSREGISTER_FogPlane = 25,
1297 D3DVSREGISTER_LightDir = 26,
1298 D3DVSREGISTER_LightPosition = 27,
1302 typedef enum D3DPSREGISTER_e
1304 D3DPSREGISTER_Alpha = 0,
1305 D3DPSREGISTER_BloomBlur_Parameters = 1,
1306 D3DPSREGISTER_ClientTime = 2,
1307 D3DPSREGISTER_Color_Ambient = 3,
1308 D3DPSREGISTER_Color_Diffuse = 4,
1309 D3DPSREGISTER_Color_Specular = 5,
1310 D3DPSREGISTER_Color_Glow = 6,
1311 D3DPSREGISTER_Color_Pants = 7,
1312 D3DPSREGISTER_Color_Shirt = 8,
1313 D3DPSREGISTER_DeferredColor_Ambient = 9,
1314 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1315 D3DPSREGISTER_DeferredColor_Specular = 11,
1316 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1317 D3DPSREGISTER_DeferredMod_Specular = 13,
1318 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1319 D3DPSREGISTER_EyePosition = 15, // unused
1320 D3DPSREGISTER_FogColor = 16,
1321 D3DPSREGISTER_FogHeightFade = 17,
1322 D3DPSREGISTER_FogPlane = 18,
1323 D3DPSREGISTER_FogPlaneViewDist = 19,
1324 D3DPSREGISTER_FogRangeRecip = 20,
1325 D3DPSREGISTER_LightColor = 21,
1326 D3DPSREGISTER_LightDir = 22, // unused
1327 D3DPSREGISTER_LightPosition = 23,
1328 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1329 D3DPSREGISTER_PixelSize = 25,
1330 D3DPSREGISTER_ReflectColor = 26,
1331 D3DPSREGISTER_ReflectFactor = 27,
1332 D3DPSREGISTER_ReflectOffset = 28,
1333 D3DPSREGISTER_RefractColor = 29,
1334 D3DPSREGISTER_Saturation = 30,
1335 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1336 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1337 D3DPSREGISTER_ScreenToDepth = 33,
1338 D3DPSREGISTER_ShadowMap_Parameters = 34,
1339 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1340 D3DPSREGISTER_SpecularPower = 36,
1341 D3DPSREGISTER_UserVec1 = 37,
1342 D3DPSREGISTER_UserVec2 = 38,
1343 D3DPSREGISTER_UserVec3 = 39,
1344 D3DPSREGISTER_UserVec4 = 40,
1345 D3DPSREGISTER_ViewTintColor = 41,
1346 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1347 D3DPSREGISTER_BloomColorSubtract = 43,
1348 D3DPSREGISTER_ViewToLight = 44, // float4x4
1349 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1350 D3DPSREGISTER_NormalmapScrollBlend = 52,
1355 /// information about each possible shader permutation
1356 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1357 /// currently selected permutation
1358 r_hlsl_permutation_t *r_hlsl_permutation;
1359 /// storage for permutations linked in the hash table
1360 memexpandablearray_t r_hlsl_permutationarray;
1362 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1364 //unsigned int hashdepth = 0;
1365 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1366 r_hlsl_permutation_t *p;
1367 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1369 if (p->mode == mode && p->permutation == permutation)
1371 //if (hashdepth > 10)
1372 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1377 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1379 p->permutation = permutation;
1380 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1381 r_hlsl_permutationhash[mode][hashindex] = p;
1382 //if (hashdepth > 10)
1383 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1387 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1390 if (!filename || !filename[0])
1392 if (!strcmp(filename, "hlsl/default.hlsl"))
1394 if (!hlslshaderstring)
1396 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1397 if (hlslshaderstring)
1398 Con_DPrintf("Loading shaders from file %s...\n", filename);
1400 hlslshaderstring = (char *)builtinhlslshaderstring;
1402 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1403 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1404 return shaderstring;
1406 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1409 if (printfromdisknotice)
1410 Con_DPrintf("from disk %s... ", filename);
1411 return shaderstring;
1413 return shaderstring;
1417 //#include <d3dx9shader.h>
1418 //#include <d3dx9mesh.h>
1420 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1422 DWORD *vsbin = NULL;
1423 DWORD *psbin = NULL;
1424 fs_offset_t vsbinsize;
1425 fs_offset_t psbinsize;
1426 // IDirect3DVertexShader9 *vs = NULL;
1427 // IDirect3DPixelShader9 *ps = NULL;
1428 ID3DXBuffer *vslog = NULL;
1429 ID3DXBuffer *vsbuffer = NULL;
1430 ID3DXConstantTable *vsconstanttable = NULL;
1431 ID3DXBuffer *pslog = NULL;
1432 ID3DXBuffer *psbuffer = NULL;
1433 ID3DXConstantTable *psconstanttable = NULL;
1436 char temp[MAX_INPUTLINE];
1437 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1438 qboolean debugshader = gl_paranoid.integer != 0;
1439 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1440 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1443 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1444 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1446 if ((!vsbin && vertstring) || (!psbin && fragstring))
1448 const char* dllnames_d3dx9 [] =
1472 dllhandle_t d3dx9_dll = NULL;
1473 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1474 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1475 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1476 dllfunction_t d3dx9_dllfuncs[] =
1478 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1479 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1480 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1483 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1485 DWORD shaderflags = 0;
1487 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1488 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1489 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1490 if (vertstring && vertstring[0])
1494 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1495 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1496 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1497 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1500 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1503 vsbinsize = vsbuffer->GetBufferSize();
1504 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1505 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1506 vsbuffer->Release();
1510 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1511 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1515 if (fragstring && fragstring[0])
1519 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1520 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1521 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1522 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1525 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1528 psbinsize = psbuffer->GetBufferSize();
1529 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1530 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1531 psbuffer->Release();
1535 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1536 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1540 Sys_UnloadLibrary(&d3dx9_dll);
1543 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1547 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1548 if (FAILED(vsresult))
1549 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1550 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1551 if (FAILED(psresult))
1552 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1554 // free the shader data
1555 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1556 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1559 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1562 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1563 int vertstring_length = 0;
1564 int geomstring_length = 0;
1565 int fragstring_length = 0;
1567 char *vertexstring, *geometrystring, *fragmentstring;
1568 char *vertstring, *geomstring, *fragstring;
1569 char permutationname[256];
1570 char cachename[256];
1571 int vertstrings_count = 0;
1572 int geomstrings_count = 0;
1573 int fragstrings_count = 0;
1574 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1575 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1576 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1581 p->vertexshader = NULL;
1582 p->pixelshader = NULL;
1584 permutationname[0] = 0;
1586 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1587 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1588 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1590 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1591 strlcat(cachename, "hlsl/", sizeof(cachename));
1593 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1594 vertstrings_count = 0;
1595 geomstrings_count = 0;
1596 fragstrings_count = 0;
1597 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1598 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1599 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1601 // the first pretext is which type of shader to compile as
1602 // (later these will all be bound together as a program object)
1603 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1604 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1605 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1607 // the second pretext is the mode (for example a light source)
1608 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1609 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1610 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1611 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1612 strlcat(cachename, modeinfo->name, sizeof(cachename));
1614 // now add all the permutation pretexts
1615 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1617 if (permutation & (1<<i))
1619 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1620 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1621 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1622 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1623 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1627 // keep line numbers correct
1628 vertstrings_list[vertstrings_count++] = "\n";
1629 geomstrings_list[geomstrings_count++] = "\n";
1630 fragstrings_list[fragstrings_count++] = "\n";
1635 R_CompileShader_AddStaticParms(mode, permutation);
1636 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1637 vertstrings_count += shaderstaticparms_count;
1638 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1639 geomstrings_count += shaderstaticparms_count;
1640 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1641 fragstrings_count += shaderstaticparms_count;
1643 // replace spaces in the cachename with _ characters
1644 for (i = 0;cachename[i];i++)
1645 if (cachename[i] == ' ')
1648 // now append the shader text itself
1649 vertstrings_list[vertstrings_count++] = vertexstring;
1650 geomstrings_list[geomstrings_count++] = geometrystring;
1651 fragstrings_list[fragstrings_count++] = fragmentstring;
1653 // if any sources were NULL, clear the respective list
1655 vertstrings_count = 0;
1656 if (!geometrystring)
1657 geomstrings_count = 0;
1658 if (!fragmentstring)
1659 fragstrings_count = 0;
1661 vertstring_length = 0;
1662 for (i = 0;i < vertstrings_count;i++)
1663 vertstring_length += strlen(vertstrings_list[i]);
1664 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1665 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1666 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1668 geomstring_length = 0;
1669 for (i = 0;i < geomstrings_count;i++)
1670 geomstring_length += strlen(geomstrings_list[i]);
1671 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1672 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1673 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1675 fragstring_length = 0;
1676 for (i = 0;i < fragstrings_count;i++)
1677 fragstring_length += strlen(fragstrings_list[i]);
1678 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1679 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1680 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1682 // try to load the cached shader, or generate one
1683 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1685 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1686 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1688 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1692 Mem_Free(vertstring);
1694 Mem_Free(geomstring);
1696 Mem_Free(fragstring);
1698 Mem_Free(vertexstring);
1700 Mem_Free(geometrystring);
1702 Mem_Free(fragmentstring);
1705 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1706 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1707 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);}
1708 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);}
1709 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);}
1710 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);}
1712 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1713 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1714 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);}
1715 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);}
1716 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);}
1717 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);}
1719 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1721 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1722 if (r_hlsl_permutation != perm)
1724 r_hlsl_permutation = perm;
1725 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1727 if (!r_hlsl_permutation->compiled)
1728 R_HLSL_CompilePermutation(perm, mode, permutation);
1729 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1731 // remove features until we find a valid permutation
1733 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1735 // reduce i more quickly whenever it would not remove any bits
1736 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1737 if (!(permutation & j))
1740 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1741 if (!r_hlsl_permutation->compiled)
1742 R_HLSL_CompilePermutation(perm, mode, permutation);
1743 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1746 if (i >= SHADERPERMUTATION_COUNT)
1748 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1749 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1750 return; // no bit left to clear, entire mode is broken
1754 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1755 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1757 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1758 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1759 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1763 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1765 DPSOFTRAST_SetShader(mode, permutation);
1766 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1767 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1768 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1771 void R_GLSL_Restart_f(void)
1773 unsigned int i, limit;
1774 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1775 Mem_Free(glslshaderstring);
1776 glslshaderstring = NULL;
1777 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1778 Mem_Free(hlslshaderstring);
1779 hlslshaderstring = NULL;
1780 switch(vid.renderpath)
1782 case RENDERPATH_D3D9:
1785 r_hlsl_permutation_t *p;
1786 r_hlsl_permutation = NULL;
1787 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1788 for (i = 0;i < limit;i++)
1790 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1792 if (p->vertexshader)
1793 IDirect3DVertexShader9_Release(p->vertexshader);
1795 IDirect3DPixelShader9_Release(p->pixelshader);
1796 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1799 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1803 case RENDERPATH_D3D10:
1804 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1806 case RENDERPATH_D3D11:
1807 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1809 case RENDERPATH_GL20:
1810 case RENDERPATH_GLES2:
1812 r_glsl_permutation_t *p;
1813 r_glsl_permutation = NULL;
1814 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1815 for (i = 0;i < limit;i++)
1817 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1819 GL_Backend_FreeProgram(p->program);
1820 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1823 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1826 case RENDERPATH_GL13:
1827 case RENDERPATH_GL11:
1829 case RENDERPATH_SOFT:
1834 void R_GLSL_DumpShader_f(void)
1839 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1842 FS_Print(file, "/* The engine may define the following macros:\n");
1843 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1844 for (i = 0;i < SHADERMODE_COUNT;i++)
1845 FS_Print(file, glslshadermodeinfo[i].pretext);
1846 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1847 FS_Print(file, shaderpermutationinfo[i].pretext);
1848 FS_Print(file, "*/\n");
1849 FS_Print(file, builtinshaderstring);
1851 Con_Printf("glsl/default.glsl written\n");
1854 Con_Printf("failed to write to glsl/default.glsl\n");
1856 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1859 FS_Print(file, "/* The engine may define the following macros:\n");
1860 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1861 for (i = 0;i < SHADERMODE_COUNT;i++)
1862 FS_Print(file, hlslshadermodeinfo[i].pretext);
1863 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864 FS_Print(file, shaderpermutationinfo[i].pretext);
1865 FS_Print(file, "*/\n");
1866 FS_Print(file, builtinhlslshaderstring);
1868 Con_Printf("hlsl/default.hlsl written\n");
1871 Con_Printf("failed to write to hlsl/default.hlsl\n");
1874 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1877 texturemode = GL_MODULATE;
1878 switch (vid.renderpath)
1880 case RENDERPATH_D3D9:
1882 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))));
1883 R_Mesh_TexBind(GL20TU_FIRST , first );
1884 R_Mesh_TexBind(GL20TU_SECOND, second);
1887 case RENDERPATH_D3D10:
1888 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1890 case RENDERPATH_D3D11:
1891 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1893 case RENDERPATH_GL20:
1894 case RENDERPATH_GLES2:
1895 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))));
1896 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1897 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1899 case RENDERPATH_GL13:
1900 R_Mesh_TexBind(0, first );
1901 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1902 R_Mesh_TexBind(1, second);
1904 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1906 case RENDERPATH_GL11:
1907 R_Mesh_TexBind(0, first );
1909 case RENDERPATH_SOFT:
1910 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))));
1911 R_Mesh_TexBind(GL20TU_FIRST , first );
1912 R_Mesh_TexBind(GL20TU_SECOND, second);
1917 void R_SetupShader_DepthOrShadow(void)
1919 switch (vid.renderpath)
1921 case RENDERPATH_D3D9:
1923 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1926 case RENDERPATH_D3D10:
1927 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929 case RENDERPATH_D3D11:
1930 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1932 case RENDERPATH_GL20:
1933 case RENDERPATH_GLES2:
1934 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1936 case RENDERPATH_GL13:
1937 R_Mesh_TexBind(0, 0);
1938 R_Mesh_TexBind(1, 0);
1940 case RENDERPATH_GL11:
1941 R_Mesh_TexBind(0, 0);
1943 case RENDERPATH_SOFT:
1944 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1949 void R_SetupShader_ShowDepth(void)
1951 switch (vid.renderpath)
1953 case RENDERPATH_D3D9:
1955 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1958 case RENDERPATH_D3D10:
1959 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1961 case RENDERPATH_D3D11:
1962 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964 case RENDERPATH_GL20:
1965 case RENDERPATH_GLES2:
1966 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1968 case RENDERPATH_GL13:
1970 case RENDERPATH_GL11:
1972 case RENDERPATH_SOFT:
1973 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1978 extern qboolean r_shadow_usingdeferredprepass;
1979 extern cvar_t r_shadow_deferred_8bitrange;
1980 extern rtexture_t *r_shadow_attenuationgradienttexture;
1981 extern rtexture_t *r_shadow_attenuation2dtexture;
1982 extern rtexture_t *r_shadow_attenuation3dtexture;
1983 extern qboolean r_shadow_usingshadowmap2d;
1984 extern qboolean r_shadow_usingshadowmaportho;
1985 extern float r_shadow_shadowmap_texturescale[2];
1986 extern float r_shadow_shadowmap_parameters[4];
1987 extern qboolean r_shadow_shadowmapvsdct;
1988 extern qboolean r_shadow_shadowmapsampler;
1989 extern int r_shadow_shadowmappcf;
1990 extern rtexture_t *r_shadow_shadowmap2dtexture;
1991 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1992 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1993 extern matrix4x4_t r_shadow_shadowmapmatrix;
1994 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1995 extern int r_shadow_prepass_width;
1996 extern int r_shadow_prepass_height;
1997 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
1998 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
1999 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2000 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2001 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2003 #define BLENDFUNC_ALLOWS_COLORMOD 1
2004 #define BLENDFUNC_ALLOWS_FOG 2
2005 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2006 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2007 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2008 static int R_BlendFuncFlags(int src, int dst)
2012 // a blendfunc allows colormod if:
2013 // a) it can never keep the destination pixel invariant, or
2014 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2015 // this is to prevent unintended side effects from colormod
2017 // a blendfunc allows fog if:
2018 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2019 // this is to prevent unintended side effects from fog
2021 // these checks are the output of fogeval.pl
2023 r |= BLENDFUNC_ALLOWS_COLORMOD;
2024 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2025 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2026 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2027 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2028 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2029 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2031 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2032 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2033 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2034 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2035 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2036 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2037 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2038 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2039 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2040 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2041 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2042 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2043 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2044 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2049 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)
2051 // select a permutation of the lighting shader appropriate to this
2052 // combination of texture, entity, light source, and fogging, only use the
2053 // minimum features necessary to avoid wasting rendering time in the
2054 // fragment shader on features that are not being used
2055 unsigned int permutation = 0;
2056 unsigned int mode = 0;
2058 static float dummy_colormod[3] = {1, 1, 1};
2059 float *colormod = rsurface.colormod;
2061 matrix4x4_t tempmatrix;
2062 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2063 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2064 permutation |= SHADERPERMUTATION_ALPHAKILL;
2065 if (rsurfacepass == RSURFPASS_BACKGROUND)
2067 // distorted background
2068 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2070 mode = SHADERMODE_WATER;
2071 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2072 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2073 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2075 // this is the right thing to do for wateralpha
2076 GL_BlendFunc(GL_ONE, GL_ZERO);
2077 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2081 // this is the right thing to do for entity alpha
2082 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2083 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2086 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2088 mode = SHADERMODE_REFRACTION;
2089 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2090 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2094 mode = SHADERMODE_GENERIC;
2095 permutation |= SHADERPERMUTATION_DIFFUSE;
2096 GL_BlendFunc(GL_ONE, GL_ZERO);
2097 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2100 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2102 if (r_glsl_offsetmapping.integer)
2104 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2105 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2106 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2107 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2108 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2110 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2111 if (r_glsl_offsetmapping_reliefmapping.integer)
2112 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2115 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2116 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2117 // normalmap (deferred prepass), may use alpha test on diffuse
2118 mode = SHADERMODE_DEFERREDGEOMETRY;
2119 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2120 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2121 GL_BlendFunc(GL_ONE, GL_ZERO);
2122 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2124 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2126 if (r_glsl_offsetmapping.integer)
2128 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2129 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2130 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2131 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2132 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2134 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2135 if (r_glsl_offsetmapping_reliefmapping.integer)
2136 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2139 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2140 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2142 mode = SHADERMODE_LIGHTSOURCE;
2143 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2144 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2146 permutation |= SHADERPERMUTATION_CUBEFILTER;
2147 if (diffusescale > 0)
2148 permutation |= SHADERPERMUTATION_DIFFUSE;
2149 if (specularscale > 0)
2150 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2151 if (r_refdef.fogenabled)
2152 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2153 if (rsurface.texture->colormapping)
2154 permutation |= SHADERPERMUTATION_COLORMAPPING;
2155 if (r_shadow_usingshadowmap2d)
2157 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2158 if(r_shadow_shadowmapvsdct)
2159 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2161 if (r_shadow_shadowmapsampler)
2162 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2163 if (r_shadow_shadowmappcf > 1)
2164 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2165 else if (r_shadow_shadowmappcf)
2166 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2168 if (rsurface.texture->reflectmasktexture)
2169 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2170 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2171 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2173 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2175 if (r_glsl_offsetmapping.integer)
2177 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2178 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2179 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2180 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2181 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2184 if (r_glsl_offsetmapping_reliefmapping.integer)
2185 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2188 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2189 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2190 // unshaded geometry (fullbright or ambient model lighting)
2191 mode = SHADERMODE_FLATCOLOR;
2192 ambientscale = diffusescale = specularscale = 0;
2193 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2194 permutation |= SHADERPERMUTATION_GLOW;
2195 if (r_refdef.fogenabled)
2196 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2197 if (rsurface.texture->colormapping)
2198 permutation |= SHADERPERMUTATION_COLORMAPPING;
2199 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2201 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2202 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2204 if (r_shadow_shadowmapsampler)
2205 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2206 if (r_shadow_shadowmappcf > 1)
2207 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2208 else if (r_shadow_shadowmappcf)
2209 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2211 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2212 permutation |= SHADERPERMUTATION_REFLECTION;
2213 if (rsurface.texture->reflectmasktexture)
2214 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2215 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2216 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2218 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2220 if (r_glsl_offsetmapping.integer)
2222 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2223 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2224 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2225 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2226 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2228 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2229 if (r_glsl_offsetmapping_reliefmapping.integer)
2230 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2233 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2234 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2235 // directional model lighting
2236 mode = SHADERMODE_LIGHTDIRECTION;
2237 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2238 permutation |= SHADERPERMUTATION_GLOW;
2239 permutation |= SHADERPERMUTATION_DIFFUSE;
2240 if (specularscale > 0)
2241 permutation |= SHADERPERMUTATION_SPECULAR;
2242 if (r_refdef.fogenabled)
2243 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2244 if (rsurface.texture->colormapping)
2245 permutation |= SHADERPERMUTATION_COLORMAPPING;
2246 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2248 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2249 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2251 if (r_shadow_shadowmapsampler)
2252 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2253 if (r_shadow_shadowmappcf > 1)
2254 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2255 else if (r_shadow_shadowmappcf)
2256 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2258 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2259 permutation |= SHADERPERMUTATION_REFLECTION;
2260 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2261 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2262 if (rsurface.texture->reflectmasktexture)
2263 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264 if (r_shadow_bouncegridtexture)
2266 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2267 if (r_shadow_bouncegriddirectional)
2268 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2270 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2271 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2275 if (r_glsl_offsetmapping.integer)
2277 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2278 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2279 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2280 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2281 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2283 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2284 if (r_glsl_offsetmapping_reliefmapping.integer)
2285 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2288 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290 // ambient model lighting
2291 mode = SHADERMODE_LIGHTDIRECTION;
2292 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2293 permutation |= SHADERPERMUTATION_GLOW;
2294 if (r_refdef.fogenabled)
2295 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2296 if (rsurface.texture->colormapping)
2297 permutation |= SHADERPERMUTATION_COLORMAPPING;
2298 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2300 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2301 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2303 if (r_shadow_shadowmapsampler)
2304 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2305 if (r_shadow_shadowmappcf > 1)
2306 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2307 else if (r_shadow_shadowmappcf)
2308 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2310 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2311 permutation |= SHADERPERMUTATION_REFLECTION;
2312 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2313 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2314 if (rsurface.texture->reflectmasktexture)
2315 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2316 if (r_shadow_bouncegridtexture)
2318 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2319 if (r_shadow_bouncegriddirectional)
2320 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2322 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2323 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327 if (r_glsl_offsetmapping.integer)
2329 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2330 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2331 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2332 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2333 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2335 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2336 if (r_glsl_offsetmapping_reliefmapping.integer)
2337 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2340 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2341 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2343 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2344 permutation |= SHADERPERMUTATION_GLOW;
2345 if (r_refdef.fogenabled)
2346 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2347 if (rsurface.texture->colormapping)
2348 permutation |= SHADERPERMUTATION_COLORMAPPING;
2349 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2351 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2352 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2354 if (r_shadow_shadowmapsampler)
2355 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2356 if (r_shadow_shadowmappcf > 1)
2357 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2358 else if (r_shadow_shadowmappcf)
2359 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2361 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2362 permutation |= SHADERPERMUTATION_REFLECTION;
2363 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2364 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2365 if (rsurface.texture->reflectmasktexture)
2366 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2367 if (FAKELIGHT_ENABLED)
2369 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2370 mode = SHADERMODE_FAKELIGHT;
2371 permutation |= SHADERPERMUTATION_DIFFUSE;
2372 if (specularscale > 0)
2373 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2375 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2377 // deluxemapping (light direction texture)
2378 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2379 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2381 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2382 permutation |= SHADERPERMUTATION_DIFFUSE;
2383 if (specularscale > 0)
2384 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2386 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2388 // fake deluxemapping (uniform light direction in tangentspace)
2389 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2390 permutation |= SHADERPERMUTATION_DIFFUSE;
2391 if (specularscale > 0)
2392 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2394 else if (rsurface.uselightmaptexture)
2396 // ordinary lightmapping (q1bsp, q3bsp)
2397 mode = SHADERMODE_LIGHTMAP;
2401 // ordinary vertex coloring (q3bsp)
2402 mode = SHADERMODE_VERTEXCOLOR;
2404 if (r_shadow_bouncegridtexture)
2406 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2407 if (r_shadow_bouncegriddirectional)
2408 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2410 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2414 colormod = dummy_colormod;
2415 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2416 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2417 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2418 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2419 switch(vid.renderpath)
2421 case RENDERPATH_D3D9:
2423 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);
2424 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2425 R_SetupShader_SetPermutationHLSL(mode, permutation);
2426 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2427 if (mode == SHADERMODE_LIGHTSOURCE)
2429 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2430 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2434 if (mode == SHADERMODE_LIGHTDIRECTION)
2436 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2439 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2440 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2441 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2442 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2443 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2445 if (mode == SHADERMODE_LIGHTSOURCE)
2447 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2448 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2449 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2450 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2451 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2453 // additive passes are only darkened by fog, not tinted
2454 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2455 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2459 if (mode == SHADERMODE_FLATCOLOR)
2461 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2463 else if (mode == SHADERMODE_LIGHTDIRECTION)
2465 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]);
2466 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2467 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);
2468 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);
2469 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2470 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2471 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2475 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2476 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2477 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);
2478 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);
2479 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2481 // additive passes are only darkened by fog, not tinted
2482 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2483 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2485 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2486 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);
2487 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2488 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2489 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2490 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2491 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2492 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2493 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2494 if (mode == SHADERMODE_WATER)
2495 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2497 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2498 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2499 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2500 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));
2501 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2502 if (rsurface.texture->pantstexture)
2503 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2505 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2506 if (rsurface.texture->shirttexture)
2507 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2509 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2510 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2511 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2512 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2513 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2514 hlslPSSetParameter3f(D3DPSREGISTER_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2515 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2516 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2518 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2519 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2520 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2521 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2522 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2523 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2524 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2525 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2526 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2527 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2528 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2529 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2530 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2531 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2532 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2533 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2534 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2535 if (rsurfacepass == RSURFPASS_BACKGROUND)
2537 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2538 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2539 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2543 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2545 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2546 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2547 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2548 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2549 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2551 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2552 if (rsurface.rtlight)
2554 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2555 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2560 case RENDERPATH_D3D10:
2561 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2563 case RENDERPATH_D3D11:
2564 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2566 case RENDERPATH_GL20:
2567 case RENDERPATH_GLES2:
2568 if (!vid.useinterleavedarrays)
2570 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);
2571 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2572 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2573 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2574 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2575 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2576 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2577 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2581 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);
2582 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2584 R_SetupShader_SetPermutationGLSL(mode, permutation);
2585 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2586 if (mode == SHADERMODE_LIGHTSOURCE)
2588 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2589 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2590 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2591 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2592 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2593 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);
2595 // additive passes are only darkened by fog, not tinted
2596 if (r_glsl_permutation->loc_FogColor >= 0)
2597 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2598 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2602 if (mode == SHADERMODE_FLATCOLOR)
2604 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2606 else if (mode == SHADERMODE_LIGHTDIRECTION)
2608 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]);
2609 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]);
2610 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);
2611 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);
2612 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);
2613 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]);
2614 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]);
2618 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]);
2619 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]);
2620 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);
2621 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);
2622 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);
2624 // additive passes are only darkened by fog, not tinted
2625 if (r_glsl_permutation->loc_FogColor >= 0)
2627 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2628 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2630 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2632 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);
2633 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]);
2634 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]);
2635 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]);
2636 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]);
2637 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2638 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2639 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2640 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]);
2642 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2643 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2644 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2645 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]);
2646 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]);
2648 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2649 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));
2650 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2651 if (r_glsl_permutation->loc_Color_Pants >= 0)
2653 if (rsurface.texture->pantstexture)
2654 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2656 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2658 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2660 if (rsurface.texture->shirttexture)
2661 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2663 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2665 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]);
2666 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2667 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2668 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2669 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform3f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2670 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]);
2671 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2672 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);}
2673 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2675 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2676 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2677 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2678 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2679 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2680 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2681 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2682 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2683 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2684 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2685 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2686 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2687 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2688 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2689 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);
2690 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2691 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2692 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2693 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2694 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2695 if (rsurfacepass == RSURFPASS_BACKGROUND)
2697 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);
2698 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);
2699 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);
2703 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);
2705 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2706 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2707 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2708 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2709 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2711 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2712 if (rsurface.rtlight)
2714 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2715 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2718 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2721 case RENDERPATH_GL13:
2722 case RENDERPATH_GL11:
2724 case RENDERPATH_SOFT:
2725 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);
2726 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2727 R_SetupShader_SetPermutationSoft(mode, permutation);
2728 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2729 if (mode == SHADERMODE_LIGHTSOURCE)
2731 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2732 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2733 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2734 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2735 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2738 // additive passes are only darkened by fog, not tinted
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2740 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2744 if (mode == SHADERMODE_FLATCOLOR)
2746 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2748 else if (mode == SHADERMODE_LIGHTDIRECTION)
2750 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]);
2751 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2752 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);
2753 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);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2755 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]);
2756 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2760 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2761 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2762 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);
2763 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);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2766 // additive passes are only darkened by fog, not tinted
2767 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2768 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2770 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2771 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);
2772 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2773 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2774 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]);
2775 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]);
2776 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2777 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2778 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2779 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2781 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2782 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2783 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2784 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2785 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]);
2787 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2788 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));
2789 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2790 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2792 if (rsurface.texture->pantstexture)
2793 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2795 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2797 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2799 if (rsurface.texture->shirttexture)
2800 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2802 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2804 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2805 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2806 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2807 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2808 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale, max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer), 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer));
2809 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2810 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2812 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2813 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2814 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2815 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2816 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2817 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2818 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2819 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2820 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2821 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2822 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2823 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2824 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2825 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2826 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2827 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2828 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2829 if (rsurfacepass == RSURFPASS_BACKGROUND)
2831 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2832 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2833 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2837 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2839 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2840 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2841 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2842 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2843 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2845 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2846 if (rsurface.rtlight)
2848 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2849 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2856 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2858 // select a permutation of the lighting shader appropriate to this
2859 // combination of texture, entity, light source, and fogging, only use the
2860 // minimum features necessary to avoid wasting rendering time in the
2861 // fragment shader on features that are not being used
2862 unsigned int permutation = 0;
2863 unsigned int mode = 0;
2864 const float *lightcolorbase = rtlight->currentcolor;
2865 float ambientscale = rtlight->ambientscale;
2866 float diffusescale = rtlight->diffusescale;
2867 float specularscale = rtlight->specularscale;
2868 // this is the location of the light in view space
2869 vec3_t viewlightorigin;
2870 // this transforms from view space (camera) to light space (cubemap)
2871 matrix4x4_t viewtolight;
2872 matrix4x4_t lighttoview;
2873 float viewtolight16f[16];
2874 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2876 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2877 if (rtlight->currentcubemap != r_texture_whitecube)
2878 permutation |= SHADERPERMUTATION_CUBEFILTER;
2879 if (diffusescale > 0)
2880 permutation |= SHADERPERMUTATION_DIFFUSE;
2881 if (specularscale > 0)
2882 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2883 if (r_shadow_usingshadowmap2d)
2885 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2886 if (r_shadow_shadowmapvsdct)
2887 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2889 if (r_shadow_shadowmapsampler)
2890 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2891 if (r_shadow_shadowmappcf > 1)
2892 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2893 else if (r_shadow_shadowmappcf)
2894 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2896 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2897 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2898 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2899 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2900 switch(vid.renderpath)
2902 case RENDERPATH_D3D9:
2904 R_SetupShader_SetPermutationHLSL(mode, permutation);
2905 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2906 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2907 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2908 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2909 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2910 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2911 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2912 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2913 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2916 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2917 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2918 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2919 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2920 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2921 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2924 case RENDERPATH_D3D10:
2925 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2927 case RENDERPATH_D3D11:
2928 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2930 case RENDERPATH_GL20:
2931 case RENDERPATH_GLES2:
2932 R_SetupShader_SetPermutationGLSL(mode, permutation);
2933 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2934 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2935 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);
2936 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);
2937 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);
2938 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]);
2939 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]);
2940 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));
2941 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]);
2942 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2944 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2945 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2946 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2947 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2948 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2949 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2951 case RENDERPATH_GL13:
2952 case RENDERPATH_GL11:
2954 case RENDERPATH_SOFT:
2955 R_SetupShader_SetPermutationGLSL(mode, permutation);
2956 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2957 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2958 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2959 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2960 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2961 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2962 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]);
2963 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));
2964 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2965 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2967 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2968 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2969 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2970 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2971 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2972 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2977 #define SKINFRAME_HASH 1024
2981 int loadsequence; // incremented each level change
2982 memexpandablearray_t array;
2983 skinframe_t *hash[SKINFRAME_HASH];
2986 r_skinframe_t r_skinframe;
2988 void R_SkinFrame_PrepareForPurge(void)
2990 r_skinframe.loadsequence++;
2991 // wrap it without hitting zero
2992 if (r_skinframe.loadsequence >= 200)
2993 r_skinframe.loadsequence = 1;
2996 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3000 // mark the skinframe as used for the purging code
3001 skinframe->loadsequence = r_skinframe.loadsequence;
3004 void R_SkinFrame_Purge(void)
3008 for (i = 0;i < SKINFRAME_HASH;i++)
3010 for (s = r_skinframe.hash[i];s;s = s->next)
3012 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3014 if (s->merged == s->base)
3016 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3017 R_PurgeTexture(s->stain );s->stain = NULL;
3018 R_PurgeTexture(s->merged);s->merged = NULL;
3019 R_PurgeTexture(s->base );s->base = NULL;
3020 R_PurgeTexture(s->pants );s->pants = NULL;
3021 R_PurgeTexture(s->shirt );s->shirt = NULL;
3022 R_PurgeTexture(s->nmap );s->nmap = NULL;
3023 R_PurgeTexture(s->gloss );s->gloss = NULL;
3024 R_PurgeTexture(s->glow );s->glow = NULL;
3025 R_PurgeTexture(s->fog );s->fog = NULL;
3026 R_PurgeTexture(s->reflect);s->reflect = NULL;
3027 s->loadsequence = 0;
3033 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3035 char basename[MAX_QPATH];
3037 Image_StripImageExtension(name, basename, sizeof(basename));
3039 if( last == NULL ) {
3041 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3042 item = r_skinframe.hash[hashindex];
3047 // linearly search through the hash bucket
3048 for( ; item ; item = item->next ) {
3049 if( !strcmp( item->basename, basename ) ) {
3056 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3060 char basename[MAX_QPATH];
3062 Image_StripImageExtension(name, basename, sizeof(basename));
3064 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3065 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3066 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3070 rtexture_t *dyntexture;
3071 // check whether its a dynamic texture
3072 dyntexture = CL_GetDynTexture( basename );
3073 if (!add && !dyntexture)
3075 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3076 memset(item, 0, sizeof(*item));
3077 strlcpy(item->basename, basename, sizeof(item->basename));
3078 item->base = dyntexture; // either NULL or dyntexture handle
3079 item->textureflags = textureflags;
3080 item->comparewidth = comparewidth;
3081 item->compareheight = compareheight;
3082 item->comparecrc = comparecrc;
3083 item->next = r_skinframe.hash[hashindex];
3084 r_skinframe.hash[hashindex] = item;
3086 else if( item->base == NULL )
3088 rtexture_t *dyntexture;
3089 // check whether its a dynamic texture
3090 // 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]
3091 dyntexture = CL_GetDynTexture( basename );
3092 item->base = dyntexture; // either NULL or dyntexture handle
3095 R_SkinFrame_MarkUsed(item);
3099 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3101 unsigned long long avgcolor[5], wsum; \
3109 for(pix = 0; pix < cnt; ++pix) \
3112 for(comp = 0; comp < 3; ++comp) \
3114 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3117 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3119 for(comp = 0; comp < 3; ++comp) \
3120 avgcolor[comp] += getpixel * w; \
3123 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3124 avgcolor[4] += getpixel; \
3126 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3128 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3129 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3130 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3131 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3134 extern cvar_t gl_picmip;
3135 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3138 unsigned char *pixels;
3139 unsigned char *bumppixels;
3140 unsigned char *basepixels = NULL;
3141 int basepixels_width = 0;
3142 int basepixels_height = 0;
3143 skinframe_t *skinframe;
3144 rtexture_t *ddsbase = NULL;
3145 qboolean ddshasalpha = false;
3146 float ddsavgcolor[4];
3147 char basename[MAX_QPATH];
3148 int miplevel = R_PicmipForFlags(textureflags);
3149 int savemiplevel = miplevel;
3152 if (cls.state == ca_dedicated)
3155 // return an existing skinframe if already loaded
3156 // if loading of the first image fails, don't make a new skinframe as it
3157 // would cause all future lookups of this to be missing
3158 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3159 if (skinframe && skinframe->base)
3162 Image_StripImageExtension(name, basename, sizeof(basename));
3164 // check for DDS texture file first
3165 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3167 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3168 if (basepixels == NULL)
3172 // FIXME handle miplevel
3174 if (developer_loading.integer)
3175 Con_Printf("loading skin \"%s\"\n", name);
3177 // we've got some pixels to store, so really allocate this new texture now
3179 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3180 skinframe->stain = NULL;
3181 skinframe->merged = NULL;
3182 skinframe->base = NULL;
3183 skinframe->pants = NULL;
3184 skinframe->shirt = NULL;
3185 skinframe->nmap = NULL;
3186 skinframe->gloss = NULL;
3187 skinframe->glow = NULL;
3188 skinframe->fog = NULL;
3189 skinframe->reflect = NULL;
3190 skinframe->hasalpha = false;
3194 skinframe->base = ddsbase;
3195 skinframe->hasalpha = ddshasalpha;
3196 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3197 if (r_loadfog && skinframe->hasalpha)
3198 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3199 //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]);
3203 basepixels_width = image_width;
3204 basepixels_height = image_height;
3205 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3206 if (textureflags & TEXF_ALPHA)
3208 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3210 if (basepixels[j] < 255)
3212 skinframe->hasalpha = true;
3216 if (r_loadfog && skinframe->hasalpha)
3218 // has transparent pixels
3219 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3220 for (j = 0;j < image_width * image_height * 4;j += 4)
3225 pixels[j+3] = basepixels[j+3];
3227 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);
3231 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3232 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3233 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3234 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3235 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3236 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3241 mymiplevel = savemiplevel;
3242 if (r_loadnormalmap)
3243 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);
3244 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3246 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3247 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3248 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3249 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252 // _norm is the name used by tenebrae and has been adopted as standard
3253 if (r_loadnormalmap && skinframe->nmap == NULL)
3255 mymiplevel = savemiplevel;
3256 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3258 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);
3262 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3264 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3265 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3266 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);
3268 Mem_Free(bumppixels);
3270 else if (r_shadow_bumpscale_basetexture.value > 0)
3272 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3273 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3274 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);
3277 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3278 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3281 // _luma is supported only for tenebrae compatibility
3282 // _glow is the preferred name
3283 mymiplevel = savemiplevel;
3284 if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel))))
3286 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3287 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3288 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3289 Mem_Free(pixels);pixels = NULL;
3292 mymiplevel = savemiplevel;
3293 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3295 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3296 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3297 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3302 mymiplevel = savemiplevel;
3303 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3305 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3306 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3307 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3312 mymiplevel = savemiplevel;
3313 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3315 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3316 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3317 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3322 mymiplevel = savemiplevel;
3323 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3325 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3326 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3327 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3333 Mem_Free(basepixels);
3338 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3339 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3342 unsigned char *temp1, *temp2;
3343 skinframe_t *skinframe;
3345 if (cls.state == ca_dedicated)
3348 // if already loaded just return it, otherwise make a new skinframe
3349 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3350 if (skinframe && skinframe->base)
3353 skinframe->stain = NULL;
3354 skinframe->merged = NULL;
3355 skinframe->base = NULL;
3356 skinframe->pants = NULL;
3357 skinframe->shirt = NULL;
3358 skinframe->nmap = NULL;
3359 skinframe->gloss = NULL;
3360 skinframe->glow = NULL;
3361 skinframe->fog = NULL;
3362 skinframe->reflect = NULL;
3363 skinframe->hasalpha = false;
3365 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3369 if (developer_loading.integer)
3370 Con_Printf("loading 32bit skin \"%s\"\n", name);
3372 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3374 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3375 temp2 = temp1 + width * height * 4;
3376 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3377 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);
3380 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3381 if (textureflags & TEXF_ALPHA)
3383 for (i = 3;i < width * height * 4;i += 4)
3385 if (skindata[i] < 255)
3387 skinframe->hasalpha = true;
3391 if (r_loadfog && skinframe->hasalpha)
3393 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3394 memcpy(fogpixels, skindata, width * height * 4);
3395 for (i = 0;i < width * height * 4;i += 4)
3396 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3397 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3398 Mem_Free(fogpixels);
3402 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3403 //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]);
3408 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3412 skinframe_t *skinframe;
3414 if (cls.state == ca_dedicated)
3417 // if already loaded just return it, otherwise make a new skinframe
3418 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3419 if (skinframe && skinframe->base)
3422 skinframe->stain = NULL;
3423 skinframe->merged = NULL;
3424 skinframe->base = NULL;
3425 skinframe->pants = NULL;
3426 skinframe->shirt = NULL;
3427 skinframe->nmap = NULL;
3428 skinframe->gloss = NULL;
3429 skinframe->glow = NULL;
3430 skinframe->fog = NULL;
3431 skinframe->reflect = NULL;
3432 skinframe->hasalpha = false;
3434 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3438 if (developer_loading.integer)
3439 Con_Printf("loading quake skin \"%s\"\n", name);
3441 // 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)
3442 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3443 memcpy(skinframe->qpixels, skindata, width*height);
3444 skinframe->qwidth = width;
3445 skinframe->qheight = height;
3448 for (i = 0;i < width * height;i++)
3449 featuresmask |= palette_featureflags[skindata[i]];
3451 skinframe->hasalpha = false;
3452 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3453 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3454 skinframe->qgeneratemerged = true;
3455 skinframe->qgeneratebase = skinframe->qhascolormapping;
3456 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3458 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3459 //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]);
3464 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3468 unsigned char *skindata;
3470 if (!skinframe->qpixels)
3473 if (!skinframe->qhascolormapping)
3474 colormapped = false;
3478 if (!skinframe->qgeneratebase)
3483 if (!skinframe->qgeneratemerged)
3487 width = skinframe->qwidth;
3488 height = skinframe->qheight;
3489 skindata = skinframe->qpixels;
3491 if (skinframe->qgeneratenmap)
3493 unsigned char *temp1, *temp2;
3494 skinframe->qgeneratenmap = false;
3495 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3496 temp2 = temp1 + width * height * 4;
3497 // use either a custom palette or the quake palette
3498 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3499 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3500 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);
3504 if (skinframe->qgenerateglow)
3506 skinframe->qgenerateglow = false;
3507 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3512 skinframe->qgeneratebase = false;
3513 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);
3514 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3515 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3519 skinframe->qgeneratemerged = false;
3520 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);
3523 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3525 Mem_Free(skinframe->qpixels);
3526 skinframe->qpixels = NULL;
3530 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)
3533 skinframe_t *skinframe;
3535 if (cls.state == ca_dedicated)
3538 // if already loaded just return it, otherwise make a new skinframe
3539 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3540 if (skinframe && skinframe->base)
3543 skinframe->stain = NULL;
3544 skinframe->merged = NULL;
3545 skinframe->base = NULL;
3546 skinframe->pants = NULL;
3547 skinframe->shirt = NULL;
3548 skinframe->nmap = NULL;
3549 skinframe->gloss = NULL;
3550 skinframe->glow = NULL;
3551 skinframe->fog = NULL;
3552 skinframe->reflect = NULL;
3553 skinframe->hasalpha = false;
3555 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3559 if (developer_loading.integer)
3560 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3562 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3563 if (textureflags & TEXF_ALPHA)
3565 for (i = 0;i < width * height;i++)
3567 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3569 skinframe->hasalpha = true;
3573 if (r_loadfog && skinframe->hasalpha)
3574 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3577 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3578 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3583 skinframe_t *R_SkinFrame_LoadMissing(void)
3585 skinframe_t *skinframe;
3587 if (cls.state == ca_dedicated)
3590 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3591 skinframe->stain = NULL;
3592 skinframe->merged = NULL;
3593 skinframe->base = NULL;
3594 skinframe->pants = NULL;
3595 skinframe->shirt = NULL;
3596 skinframe->nmap = NULL;
3597 skinframe->gloss = NULL;
3598 skinframe->glow = NULL;
3599 skinframe->fog = NULL;
3600 skinframe->reflect = NULL;
3601 skinframe->hasalpha = false;
3603 skinframe->avgcolor[0] = rand() / RAND_MAX;
3604 skinframe->avgcolor[1] = rand() / RAND_MAX;
3605 skinframe->avgcolor[2] = rand() / RAND_MAX;
3606 skinframe->avgcolor[3] = 1;
3611 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3612 typedef struct suffixinfo_s
3615 qboolean flipx, flipy, flipdiagonal;
3618 static suffixinfo_t suffix[3][6] =
3621 {"px", false, false, false},
3622 {"nx", false, false, false},
3623 {"py", false, false, false},
3624 {"ny", false, false, false},
3625 {"pz", false, false, false},
3626 {"nz", false, false, false}
3629 {"posx", false, false, false},
3630 {"negx", false, false, false},
3631 {"posy", false, false, false},
3632 {"negy", false, false, false},
3633 {"posz", false, false, false},
3634 {"negz", false, false, false}
3637 {"rt", true, false, true},
3638 {"lf", false, true, true},
3639 {"ft", true, true, false},
3640 {"bk", false, false, false},
3641 {"up", true, false, true},
3642 {"dn", true, false, true}
3646 static int componentorder[4] = {0, 1, 2, 3};
3648 rtexture_t *R_LoadCubemap(const char *basename)
3650 int i, j, cubemapsize;
3651 unsigned char *cubemappixels, *image_buffer;
3652 rtexture_t *cubemaptexture;
3654 // must start 0 so the first loadimagepixels has no requested width/height
3656 cubemappixels = NULL;
3657 cubemaptexture = NULL;
3658 // keep trying different suffix groups (posx, px, rt) until one loads
3659 for (j = 0;j < 3 && !cubemappixels;j++)
3661 // load the 6 images in the suffix group
3662 for (i = 0;i < 6;i++)
3664 // generate an image name based on the base and and suffix
3665 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3667 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3669 // an image loaded, make sure width and height are equal
3670 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3672 // if this is the first image to load successfully, allocate the cubemap memory
3673 if (!cubemappixels && image_width >= 1)
3675 cubemapsize = image_width;
3676 // note this clears to black, so unavailable sides are black
3677 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3679 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3681 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);
3684 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3686 Mem_Free(image_buffer);
3690 // if a cubemap loaded, upload it
3693 if (developer_loading.integer)
3694 Con_Printf("loading cubemap \"%s\"\n", basename);
3696 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3697 Mem_Free(cubemappixels);
3701 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3702 if (developer_loading.integer)
3704 Con_Printf("(tried tried images ");
3705 for (j = 0;j < 3;j++)
3706 for (i = 0;i < 6;i++)
3707 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3708 Con_Print(" and was unable to find any of them).\n");
3711 return cubemaptexture;
3714 rtexture_t *R_GetCubemap(const char *basename)
3717 for (i = 0;i < r_texture_numcubemaps;i++)
3718 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3719 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3720 if (i >= MAX_CUBEMAPS)
3721 return r_texture_whitecube;
3722 r_texture_numcubemaps++;
3723 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3724 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3725 return r_texture_cubemaps[i].texture;
3728 void R_FreeCubemaps(void)
3731 for (i = 0;i < r_texture_numcubemaps;i++)
3733 if (developer_loading.integer)
3734 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3735 if (r_texture_cubemaps[i].texture)
3736 R_FreeTexture(r_texture_cubemaps[i].texture);
3738 r_texture_numcubemaps = 0;
3741 void R_Main_FreeViewCache(void)
3743 if (r_refdef.viewcache.entityvisible)
3744 Mem_Free(r_refdef.viewcache.entityvisible);
3745 if (r_refdef.viewcache.world_pvsbits)
3746 Mem_Free(r_refdef.viewcache.world_pvsbits);
3747 if (r_refdef.viewcache.world_leafvisible)
3748 Mem_Free(r_refdef.viewcache.world_leafvisible);
3749 if (r_refdef.viewcache.world_surfacevisible)
3750 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3751 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3754 void R_Main_ResizeViewCache(void)
3756 int numentities = r_refdef.scene.numentities;
3757 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3758 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3759 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3760 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3761 if (r_refdef.viewcache.maxentities < numentities)
3763 r_refdef.viewcache.maxentities = numentities;
3764 if (r_refdef.viewcache.entityvisible)
3765 Mem_Free(r_refdef.viewcache.entityvisible);
3766 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3768 if (r_refdef.viewcache.world_numclusters != numclusters)
3770 r_refdef.viewcache.world_numclusters = numclusters;
3771 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3772 if (r_refdef.viewcache.world_pvsbits)
3773 Mem_Free(r_refdef.viewcache.world_pvsbits);
3774 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3776 if (r_refdef.viewcache.world_numleafs != numleafs)
3778 r_refdef.viewcache.world_numleafs = numleafs;
3779 if (r_refdef.viewcache.world_leafvisible)
3780 Mem_Free(r_refdef.viewcache.world_leafvisible);
3781 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3783 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3785 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3786 if (r_refdef.viewcache.world_surfacevisible)
3787 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3788 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3792 extern rtexture_t *loadingscreentexture;
3793 void gl_main_start(void)
3795 loadingscreentexture = NULL;
3796 r_texture_blanknormalmap = NULL;
3797 r_texture_white = NULL;
3798 r_texture_grey128 = NULL;
3799 r_texture_black = NULL;
3800 r_texture_whitecube = NULL;
3801 r_texture_normalizationcube = NULL;
3802 r_texture_fogattenuation = NULL;
3803 r_texture_fogheighttexture = NULL;
3804 r_texture_gammaramps = NULL;
3805 r_texture_numcubemaps = 0;
3807 r_loaddds = r_texture_dds_load.integer != 0;
3808 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3810 switch(vid.renderpath)
3812 case RENDERPATH_GL20:
3813 case RENDERPATH_D3D9:
3814 case RENDERPATH_D3D10:
3815 case RENDERPATH_D3D11:
3816 case RENDERPATH_SOFT:
3817 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3818 Cvar_SetValueQuick(&gl_combine, 1);
3819 Cvar_SetValueQuick(&r_glsl, 1);
3820 r_loadnormalmap = true;
3824 case RENDERPATH_GL13:
3825 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3826 Cvar_SetValueQuick(&gl_combine, 1);
3827 Cvar_SetValueQuick(&r_glsl, 0);
3828 r_loadnormalmap = false;
3829 r_loadgloss = false;
3832 case RENDERPATH_GL11:
3833 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3834 Cvar_SetValueQuick(&gl_combine, 0);
3835 Cvar_SetValueQuick(&r_glsl, 0);
3836 r_loadnormalmap = false;
3837 r_loadgloss = false;
3840 case RENDERPATH_GLES2:
3841 Cvar_SetValueQuick(&r_textureunits, 1);
3842 Cvar_SetValueQuick(&gl_combine, 1);
3843 Cvar_SetValueQuick(&r_glsl, 1);
3844 r_loadnormalmap = true;
3845 r_loadgloss = false;
3851 R_FrameData_Reset();
3855 memset(r_queries, 0, sizeof(r_queries));
3857 r_qwskincache = NULL;
3858 r_qwskincache_size = 0;
3860 // due to caching of texture_t references, the collision cache must be reset
3861 Collision_Cache_Reset(true);
3863 // set up r_skinframe loading system for textures
3864 memset(&r_skinframe, 0, sizeof(r_skinframe));
3865 r_skinframe.loadsequence = 1;
3866 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3868 r_main_texturepool = R_AllocTexturePool();
3869 R_BuildBlankTextures();
3871 if (vid.support.arb_texture_cube_map)
3874 R_BuildNormalizationCube();
3876 r_texture_fogattenuation = NULL;
3877 r_texture_fogheighttexture = NULL;
3878 r_texture_gammaramps = NULL;
3879 //r_texture_fogintensity = NULL;
3880 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3881 memset(&r_waterstate, 0, sizeof(r_waterstate));
3882 r_glsl_permutation = NULL;
3883 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3884 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3885 glslshaderstring = NULL;
3887 r_hlsl_permutation = NULL;
3888 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3889 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3891 hlslshaderstring = NULL;
3892 memset(&r_svbsp, 0, sizeof (r_svbsp));
3894 r_refdef.fogmasktable_density = 0;
3897 void gl_main_shutdown(void)
3900 R_FrameData_Reset();
3902 R_Main_FreeViewCache();
3904 switch(vid.renderpath)
3906 case RENDERPATH_GL11:
3907 case RENDERPATH_GL13:
3908 case RENDERPATH_GL20:
3909 case RENDERPATH_GLES2:
3911 qglDeleteQueriesARB(r_maxqueries, r_queries);
3913 case RENDERPATH_D3D9:
3914 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3916 case RENDERPATH_D3D10:
3917 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3919 case RENDERPATH_D3D11:
3920 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3922 case RENDERPATH_SOFT:
3928 memset(r_queries, 0, sizeof(r_queries));
3930 r_qwskincache = NULL;
3931 r_qwskincache_size = 0;
3933 // clear out the r_skinframe state
3934 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3935 memset(&r_skinframe, 0, sizeof(r_skinframe));
3938 Mem_Free(r_svbsp.nodes);
3939 memset(&r_svbsp, 0, sizeof (r_svbsp));
3940 R_FreeTexturePool(&r_main_texturepool);
3941 loadingscreentexture = NULL;
3942 r_texture_blanknormalmap = NULL;
3943 r_texture_white = NULL;
3944 r_texture_grey128 = NULL;
3945 r_texture_black = NULL;
3946 r_texture_whitecube = NULL;
3947 r_texture_normalizationcube = NULL;
3948 r_texture_fogattenuation = NULL;
3949 r_texture_fogheighttexture = NULL;
3950 r_texture_gammaramps = NULL;
3951 r_texture_numcubemaps = 0;
3952 //r_texture_fogintensity = NULL;
3953 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3954 memset(&r_waterstate, 0, sizeof(r_waterstate));
3957 r_glsl_permutation = NULL;
3958 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3959 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3960 glslshaderstring = NULL;
3962 r_hlsl_permutation = NULL;
3963 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3964 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3966 hlslshaderstring = NULL;
3969 extern void CL_ParseEntityLump(char *entitystring);
3970 void gl_main_newmap(void)
3972 // FIXME: move this code to client
3973 char *entities, entname[MAX_QPATH];
3975 Mem_Free(r_qwskincache);
3976 r_qwskincache = NULL;
3977 r_qwskincache_size = 0;
3980 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3981 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3983 CL_ParseEntityLump(entities);
3987 if (cl.worldmodel->brush.entities)
3988 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3990 R_Main_FreeViewCache();
3992 R_FrameData_Reset();
3995 void GL_Main_Init(void)
3997 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
3999 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4000 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4001 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4002 if (gamemode == GAME_NEHAHRA)
4004 Cvar_RegisterVariable (&gl_fogenable);
4005 Cvar_RegisterVariable (&gl_fogdensity);
4006 Cvar_RegisterVariable (&gl_fogred);
4007 Cvar_RegisterVariable (&gl_foggreen);
4008 Cvar_RegisterVariable (&gl_fogblue);
4009 Cvar_RegisterVariable (&gl_fogstart);
4010 Cvar_RegisterVariable (&gl_fogend);
4011 Cvar_RegisterVariable (&gl_skyclip);
4013 Cvar_RegisterVariable(&r_motionblur);
4014 Cvar_RegisterVariable(&r_motionblur_maxblur);
4015 Cvar_RegisterVariable(&r_motionblur_bmin);
4016 Cvar_RegisterVariable(&r_motionblur_vmin);
4017 Cvar_RegisterVariable(&r_motionblur_vmax);
4018 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4019 Cvar_RegisterVariable(&r_motionblur_randomize);
4020 Cvar_RegisterVariable(&r_damageblur);
4021 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4022 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4023 Cvar_RegisterVariable(&r_equalize_entities_by);
4024 Cvar_RegisterVariable(&r_equalize_entities_to);
4025 Cvar_RegisterVariable(&r_depthfirst);
4026 Cvar_RegisterVariable(&r_useinfinitefarclip);
4027 Cvar_RegisterVariable(&r_farclip_base);
4028 Cvar_RegisterVariable(&r_farclip_world);
4029 Cvar_RegisterVariable(&r_nearclip);
4030 Cvar_RegisterVariable(&r_showbboxes);
4031 Cvar_RegisterVariable(&r_showsurfaces);
4032 Cvar_RegisterVariable(&r_showtris);
4033 Cvar_RegisterVariable(&r_shownormals);
4034 Cvar_RegisterVariable(&r_showlighting);
4035 Cvar_RegisterVariable(&r_showshadowvolumes);
4036 Cvar_RegisterVariable(&r_showcollisionbrushes);
4037 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4038 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4039 Cvar_RegisterVariable(&r_showdisabledepthtest);
4040 Cvar_RegisterVariable(&r_drawportals);
4041 Cvar_RegisterVariable(&r_drawentities);
4042 Cvar_RegisterVariable(&r_draw2d);
4043 Cvar_RegisterVariable(&r_drawworld);
4044 Cvar_RegisterVariable(&r_cullentities_trace);
4045 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4046 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4047 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4048 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4049 Cvar_RegisterVariable(&r_drawviewmodel);
4050 Cvar_RegisterVariable(&r_drawexteriormodel);
4051 Cvar_RegisterVariable(&r_speeds);
4052 Cvar_RegisterVariable(&r_fullbrights);
4053 Cvar_RegisterVariable(&r_wateralpha);
4054 Cvar_RegisterVariable(&r_dynamic);
4055 Cvar_RegisterVariable(&r_fakelight);
4056 Cvar_RegisterVariable(&r_fakelight_intensity);
4057 Cvar_RegisterVariable(&r_fullbright);
4058 Cvar_RegisterVariable(&r_shadows);
4059 Cvar_RegisterVariable(&r_shadows_darken);
4060 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4061 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4062 Cvar_RegisterVariable(&r_shadows_throwdistance);
4063 Cvar_RegisterVariable(&r_shadows_throwdirection);
4064 Cvar_RegisterVariable(&r_shadows_focus);
4065 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4066 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4067 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4068 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4069 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4070 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4071 Cvar_RegisterVariable(&r_fog_exp2);
4072 Cvar_RegisterVariable(&r_drawfog);
4073 Cvar_RegisterVariable(&r_transparentdepthmasking);
4074 Cvar_RegisterVariable(&r_texture_dds_load);
4075 Cvar_RegisterVariable(&r_texture_dds_save);
4076 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4077 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4078 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4079 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4080 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4081 Cvar_RegisterVariable(&r_textureunits);
4082 Cvar_RegisterVariable(&gl_combine);
4083 Cvar_RegisterVariable(&r_glsl);
4084 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4085 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4086 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4087 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4088 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4089 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4090 Cvar_RegisterVariable(&r_glsl_postprocess);
4091 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4092 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4093 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4094 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4095 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4096 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4097 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4098 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4100 Cvar_RegisterVariable(&r_water);
4101 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4102 Cvar_RegisterVariable(&r_water_clippingplanebias);
4103 Cvar_RegisterVariable(&r_water_refractdistort);
4104 Cvar_RegisterVariable(&r_water_reflectdistort);
4105 Cvar_RegisterVariable(&r_water_scissormode);
4106 Cvar_RegisterVariable(&r_lerpsprites);
4107 Cvar_RegisterVariable(&r_lerpmodels);
4108 Cvar_RegisterVariable(&r_lerplightstyles);
4109 Cvar_RegisterVariable(&r_waterscroll);
4110 Cvar_RegisterVariable(&r_bloom);
4111 Cvar_RegisterVariable(&r_bloom_colorscale);
4112 Cvar_RegisterVariable(&r_bloom_brighten);
4113 Cvar_RegisterVariable(&r_bloom_blur);
4114 Cvar_RegisterVariable(&r_bloom_resolution);
4115 Cvar_RegisterVariable(&r_bloom_colorexponent);
4116 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4117 Cvar_RegisterVariable(&r_hdr);
4118 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4119 Cvar_RegisterVariable(&r_hdr_glowintensity);
4120 Cvar_RegisterVariable(&r_hdr_range);
4121 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4122 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4123 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4124 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4125 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4126 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4127 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4128 Cvar_RegisterVariable(&developer_texturelogging);
4129 Cvar_RegisterVariable(&gl_lightmaps);
4130 Cvar_RegisterVariable(&r_test);
4131 Cvar_RegisterVariable(&r_glsl_saturation);
4132 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4133 Cvar_RegisterVariable(&r_framedatasize);
4134 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4135 Cvar_SetValue("r_fullbrights", 0);
4136 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4138 Cvar_RegisterVariable(&r_track_sprites);
4139 Cvar_RegisterVariable(&r_track_sprites_flags);
4140 Cvar_RegisterVariable(&r_track_sprites_scalew);
4141 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4142 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4143 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4144 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4145 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4148 extern void R_Textures_Init(void);
4149 extern void GL_Draw_Init(void);
4150 extern void GL_Main_Init(void);
4151 extern void R_Shadow_Init(void);
4152 extern void R_Sky_Init(void);
4153 extern void GL_Surf_Init(void);
4154 extern void R_Particles_Init(void);
4155 extern void R_Explosion_Init(void);
4156 extern void gl_backend_init(void);
4157 extern void Sbar_Init(void);
4158 extern void R_LightningBeams_Init(void);
4159 extern void Mod_RenderInit(void);
4160 extern void Font_Init(void);
4162 void Render_Init(void)
4175 R_LightningBeams_Init();
4184 extern char *ENGINE_EXTENSIONS;
4187 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4188 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4189 gl_version = (const char *)qglGetString(GL_VERSION);
4190 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4194 if (!gl_platformextensions)
4195 gl_platformextensions = "";
4197 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4198 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4199 Con_Printf("GL_VERSION: %s\n", gl_version);
4200 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4201 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4203 VID_CheckExtensions();
4205 // LordHavoc: report supported extensions
4206 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4208 // clear to black (loading plaque will be seen over this)
4209 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4212 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4216 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4218 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4221 p = r_refdef.view.frustum + i;
4226 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4230 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4234 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4238 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4242 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4246 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4250 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4254 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4262 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4266 for (i = 0;i < numplanes;i++)
4273 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4277 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4281 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4285 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4289 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4293 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4297 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4301 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4309 //==================================================================================
4311 // LordHavoc: this stores temporary data used within the same frame
4313 typedef struct r_framedata_mem_s
4315 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4316 size_t size; // how much usable space
4317 size_t current; // how much space in use
4318 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4319 size_t wantedsize; // how much space was allocated
4320 unsigned char *data; // start of real data (16byte aligned)
4324 static r_framedata_mem_t *r_framedata_mem;
4326 void R_FrameData_Reset(void)
4328 while (r_framedata_mem)
4330 r_framedata_mem_t *next = r_framedata_mem->purge;
4331 Mem_Free(r_framedata_mem);
4332 r_framedata_mem = next;
4336 void R_FrameData_Resize(void)
4339 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4340 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4341 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4343 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4344 newmem->wantedsize = wantedsize;
4345 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4346 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4347 newmem->current = 0;
4349 newmem->purge = r_framedata_mem;
4350 r_framedata_mem = newmem;
4354 void R_FrameData_NewFrame(void)
4356 R_FrameData_Resize();
4357 if (!r_framedata_mem)
4359 // if we ran out of space on the last frame, free the old memory now
4360 while (r_framedata_mem->purge)
4362 // repeatedly remove the second item in the list, leaving only head
4363 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4364 Mem_Free(r_framedata_mem->purge);
4365 r_framedata_mem->purge = next;
4367 // reset the current mem pointer
4368 r_framedata_mem->current = 0;
4369 r_framedata_mem->mark = 0;
4372 void *R_FrameData_Alloc(size_t size)
4376 // align to 16 byte boundary - the data pointer is already aligned, so we
4377 // only need to ensure the size of every allocation is also aligned
4378 size = (size + 15) & ~15;
4380 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4382 // emergency - we ran out of space, allocate more memory
4383 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4384 R_FrameData_Resize();
4387 data = r_framedata_mem->data + r_framedata_mem->current;
4388 r_framedata_mem->current += size;
4390 // count the usage for stats
4391 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4392 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4394 return (void *)data;
4397 void *R_FrameData_Store(size_t size, void *data)
4399 void *d = R_FrameData_Alloc(size);
4401 memcpy(d, data, size);
4405 void R_FrameData_SetMark(void)
4407 if (!r_framedata_mem)
4409 r_framedata_mem->mark = r_framedata_mem->current;
4412 void R_FrameData_ReturnToMark(void)
4414 if (!r_framedata_mem)
4416 r_framedata_mem->current = r_framedata_mem->mark;
4419 //==================================================================================
4421 // LordHavoc: animcache originally written by Echon, rewritten since then
4424 * Animation cache prevents re-generating mesh data for an animated model
4425 * multiple times in one frame for lighting, shadowing, reflections, etc.
4428 void R_AnimCache_Free(void)
4432 void R_AnimCache_ClearCache(void)
4435 entity_render_t *ent;
4437 for (i = 0;i < r_refdef.scene.numentities;i++)
4439 ent = r_refdef.scene.entities[i];
4440 ent->animcache_vertex3f = NULL;
4441 ent->animcache_normal3f = NULL;
4442 ent->animcache_svector3f = NULL;
4443 ent->animcache_tvector3f = NULL;
4444 ent->animcache_vertexmesh = NULL;
4445 ent->animcache_vertex3fbuffer = NULL;
4446 ent->animcache_vertexmeshbuffer = NULL;
4450 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4454 // check if we need the meshbuffers
4455 if (!vid.useinterleavedarrays)
4458 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4459 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4460 // TODO: upload vertex3f buffer?
4461 if (ent->animcache_vertexmesh)
4463 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4464 for (i = 0;i < numvertices;i++)
4465 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4466 if (ent->animcache_svector3f)
4467 for (i = 0;i < numvertices;i++)
4468 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4469 if (ent->animcache_tvector3f)
4470 for (i = 0;i < numvertices;i++)
4471 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4472 if (ent->animcache_normal3f)
4473 for (i = 0;i < numvertices;i++)
4474 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4475 // TODO: upload vertexmeshbuffer?
4479 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4481 dp_model_t *model = ent->model;
4483 // see if it's already cached this frame
4484 if (ent->animcache_vertex3f)
4486 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4487 if (wantnormals || wanttangents)
4489 if (ent->animcache_normal3f)
4490 wantnormals = false;
4491 if (ent->animcache_svector3f)
4492 wanttangents = false;
4493 if (wantnormals || wanttangents)
4495 numvertices = model->surfmesh.num_vertices;
4497 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4500 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4501 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4503 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4504 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4510 // see if this ent is worth caching
4511 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4513 // get some memory for this entity and generate mesh data
4514 numvertices = model->surfmesh.num_vertices;
4515 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4517 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4520 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4521 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4523 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4524 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4529 void R_AnimCache_CacheVisibleEntities(void)
4532 qboolean wantnormals = true;
4533 qboolean wanttangents = !r_showsurfaces.integer;
4535 switch(vid.renderpath)
4537 case RENDERPATH_GL20:
4538 case RENDERPATH_D3D9:
4539 case RENDERPATH_D3D10:
4540 case RENDERPATH_D3D11:
4541 case RENDERPATH_GLES2:
4543 case RENDERPATH_GL13:
4544 case RENDERPATH_GL11:
4545 wanttangents = false;
4547 case RENDERPATH_SOFT:
4551 if (r_shownormals.integer)
4552 wanttangents = wantnormals = true;
4554 // TODO: thread this
4555 // NOTE: R_PrepareRTLights() also caches entities
4557 for (i = 0;i < r_refdef.scene.numentities;i++)
4558 if (r_refdef.viewcache.entityvisible[i])
4559 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4562 //==================================================================================
4564 static void R_View_UpdateEntityLighting (void)
4567 entity_render_t *ent;
4568 vec3_t tempdiffusenormal, avg;
4569 vec_t f, fa, fd, fdd;
4570 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4572 for (i = 0;i < r_refdef.scene.numentities;i++)
4574 ent = r_refdef.scene.entities[i];
4576 // skip unseen models
4577 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4581 if (ent->model && ent->model->brush.num_leafs)
4583 // TODO: use modellight for r_ambient settings on world?
4584 VectorSet(ent->modellight_ambient, 0, 0, 0);
4585 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4586 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4590 // fetch the lighting from the worldmodel data
4591 VectorClear(ent->modellight_ambient);
4592 VectorClear(ent->modellight_diffuse);
4593 VectorClear(tempdiffusenormal);
4594 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4597 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4599 // complete lightning for lit sprites
4600 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4601 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4603 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4604 org[2] = org[2] + r_overheadsprites_pushback.value;
4605 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4608 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4610 if(ent->flags & RENDER_EQUALIZE)
4612 // first fix up ambient lighting...
4613 if(r_equalize_entities_minambient.value > 0)
4615 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4618 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4619 if(fa < r_equalize_entities_minambient.value * fd)
4622 // fa'/fd' = minambient
4623 // fa'+0.25*fd' = fa+0.25*fd
4625 // fa' = fd' * minambient
4626 // fd'*(0.25+minambient) = fa+0.25*fd
4628 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4629 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4631 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4632 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
4633 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4634 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4639 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4641 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4642 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4646 // adjust brightness and saturation to target
4647 avg[0] = avg[1] = avg[2] = fa / f;
4648 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4649 avg[0] = avg[1] = avg[2] = fd / f;
4650 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4656 VectorSet(ent->modellight_ambient, 1, 1, 1);
4658 // move the light direction into modelspace coordinates for lighting code
4659 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4660 if(VectorLength2(ent->modellight_lightdir) == 0)
4661 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4662 VectorNormalize(ent->modellight_lightdir);
4666 #define MAX_LINEOFSIGHTTRACES 64
4668 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4671 vec3_t boxmins, boxmaxs;
4674 dp_model_t *model = r_refdef.scene.worldmodel;
4676 if (!model || !model->brush.TraceLineOfSight)
4679 // expand the box a little
4680 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4681 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4682 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4683 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4684 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4685 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4687 // return true if eye is inside enlarged box
4688 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4692 VectorCopy(eye, start);
4693 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4694 if (model->brush.TraceLineOfSight(model, start, end))
4697 // try various random positions
4698 for (i = 0;i < numsamples;i++)
4700 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4701 if (model->brush.TraceLineOfSight(model, start, end))
4709 static void R_View_UpdateEntityVisible (void)
4714 entity_render_t *ent;
4716 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4717 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4718 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4719 : RENDER_EXTERIORMODEL;
4720 if (!r_drawviewmodel.integer)
4721 renderimask |= RENDER_VIEWMODEL;
4722 if (!r_drawexteriormodel.integer)
4723 renderimask |= RENDER_EXTERIORMODEL;
4724 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4726 // worldmodel can check visibility
4727 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4728 for (i = 0;i < r_refdef.scene.numentities;i++)
4730 ent = r_refdef.scene.entities[i];
4731 if (!(ent->flags & renderimask))
4732 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)))
4733 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))
4734 r_refdef.viewcache.entityvisible[i] = true;
4736 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4737 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4739 for (i = 0;i < r_refdef.scene.numentities;i++)
4741 ent = r_refdef.scene.entities[i];
4742 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4744 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4746 continue; // temp entities do pvs only
4747 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4748 ent->last_trace_visibility = realtime;
4749 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4750 r_refdef.viewcache.entityvisible[i] = 0;
4757 // no worldmodel or it can't check visibility
4758 for (i = 0;i < r_refdef.scene.numentities;i++)
4760 ent = r_refdef.scene.entities[i];
4761 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));
4766 /// only used if skyrendermasked, and normally returns false
4767 int R_DrawBrushModelsSky (void)
4770 entity_render_t *ent;
4773 for (i = 0;i < r_refdef.scene.numentities;i++)
4775 if (!r_refdef.viewcache.entityvisible[i])
4777 ent = r_refdef.scene.entities[i];
4778 if (!ent->model || !ent->model->DrawSky)
4780 ent->model->DrawSky(ent);
4786 static void R_DrawNoModel(entity_render_t *ent);
4787 static void R_DrawModels(void)
4790 entity_render_t *ent;
4792 for (i = 0;i < r_refdef.scene.numentities;i++)
4794 if (!r_refdef.viewcache.entityvisible[i])
4796 ent = r_refdef.scene.entities[i];
4797 r_refdef.stats.entities++;
4798 if (ent->model && ent->model->Draw != NULL)
4799 ent->model->Draw(ent);
4805 static void R_DrawModelsDepth(void)
4808 entity_render_t *ent;
4810 for (i = 0;i < r_refdef.scene.numentities;i++)
4812 if (!r_refdef.viewcache.entityvisible[i])
4814 ent = r_refdef.scene.entities[i];
4815 if (ent->model && ent->model->DrawDepth != NULL)
4816 ent->model->DrawDepth(ent);
4820 static void R_DrawModelsDebug(void)
4823 entity_render_t *ent;
4825 for (i = 0;i < r_refdef.scene.numentities;i++)
4827 if (!r_refdef.viewcache.entityvisible[i])
4829 ent = r_refdef.scene.entities[i];
4830 if (ent->model && ent->model->DrawDebug != NULL)
4831 ent->model->DrawDebug(ent);
4835 static void R_DrawModelsAddWaterPlanes(void)
4838 entity_render_t *ent;
4840 for (i = 0;i < r_refdef.scene.numentities;i++)
4842 if (!r_refdef.viewcache.entityvisible[i])
4844 ent = r_refdef.scene.entities[i];
4845 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4846 ent->model->DrawAddWaterPlanes(ent);
4850 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4852 if (r_hdr_irisadaptation.integer)
4856 vec3_t diffusenormal;
4861 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4862 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4863 brightness = max(0.0000001f, brightness);
4864 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4865 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4866 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4867 current = r_hdr_irisadaptation_value.value;
4869 current = min(current + adjust, goal);
4870 else if (current > goal)
4871 current = max(current - adjust, goal);
4872 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4873 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4875 else if (r_hdr_irisadaptation_value.value != 1.0f)
4876 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4879 static void R_View_SetFrustum(const int *scissor)
4882 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4883 vec3_t forward, left, up, origin, v;
4887 // flipped x coordinates (because x points left here)
4888 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4889 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4891 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4892 switch(vid.renderpath)
4894 case RENDERPATH_D3D9:
4895 case RENDERPATH_D3D10:
4896 case RENDERPATH_D3D11:
4897 case RENDERPATH_SOFT:
4898 // non-flipped y coordinates
4899 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4900 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4902 case RENDERPATH_GL11:
4903 case RENDERPATH_GL13:
4904 case RENDERPATH_GL20:
4905 case RENDERPATH_GLES2:
4906 // non-flipped y coordinates
4907 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4908 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4913 // we can't trust r_refdef.view.forward and friends in reflected scenes
4914 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4917 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4918 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4919 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4920 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4921 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4922 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4923 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4924 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4925 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4926 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4927 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4928 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4932 zNear = r_refdef.nearclip;
4933 nudge = 1.0 - 1.0 / (1<<23);
4934 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4935 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4936 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4937 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4938 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4939 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4940 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4941 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4947 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4948 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4949 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4950 r_refdef.view.frustum[0].dist = m[15] - m[12];
4952 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4953 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4954 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4955 r_refdef.view.frustum[1].dist = m[15] + m[12];
4957 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4958 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4959 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4960 r_refdef.view.frustum[2].dist = m[15] - m[13];
4962 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4963 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4964 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4965 r_refdef.view.frustum[3].dist = m[15] + m[13];
4967 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4968 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4969 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4970 r_refdef.view.frustum[4].dist = m[15] - m[14];
4972 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4973 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4974 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4975 r_refdef.view.frustum[5].dist = m[15] + m[14];
4978 if (r_refdef.view.useperspective)
4980 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4981 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]);
4982 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]);
4983 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]);
4984 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]);
4986 // then the normals from the corners relative to origin
4987 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4988 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4989 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4990 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4992 // in a NORMAL view, forward cross left == up
4993 // in a REFLECTED view, forward cross left == down
4994 // so our cross products above need to be adjusted for a left handed coordinate system
4995 CrossProduct(forward, left, v);
4996 if(DotProduct(v, up) < 0)
4998 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
4999 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5000 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5001 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5004 // Leaving those out was a mistake, those were in the old code, and they
5005 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5006 // I couldn't reproduce it after adding those normalizations. --blub
5007 VectorNormalize(r_refdef.view.frustum[0].normal);
5008 VectorNormalize(r_refdef.view.frustum[1].normal);
5009 VectorNormalize(r_refdef.view.frustum[2].normal);
5010 VectorNormalize(r_refdef.view.frustum[3].normal);
5012 // make the corners absolute
5013 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5014 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5015 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5016 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5019 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5021 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5022 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5023 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5024 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5025 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5029 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5030 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5031 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5032 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5033 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5034 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5035 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5036 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5037 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5038 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5040 r_refdef.view.numfrustumplanes = 5;
5042 if (r_refdef.view.useclipplane)
5044 r_refdef.view.numfrustumplanes = 6;
5045 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5048 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5049 PlaneClassify(r_refdef.view.frustum + i);
5051 // LordHavoc: note to all quake engine coders, Quake had a special case
5052 // for 90 degrees which assumed a square view (wrong), so I removed it,
5053 // Quake2 has it disabled as well.
5055 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5056 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5057 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5058 //PlaneClassify(&frustum[0]);
5060 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5061 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5062 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5063 //PlaneClassify(&frustum[1]);
5065 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5066 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5067 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5068 //PlaneClassify(&frustum[2]);
5070 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5071 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5072 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5073 //PlaneClassify(&frustum[3]);
5076 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5077 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5078 //PlaneClassify(&frustum[4]);
5081 void R_View_UpdateWithScissor(const int *myscissor)
5083 R_Main_ResizeViewCache();
5084 R_View_SetFrustum(myscissor);
5085 R_View_WorldVisibility(r_refdef.view.useclipplane);
5086 R_View_UpdateEntityVisible();
5087 R_View_UpdateEntityLighting();
5090 void R_View_Update(void)
5092 R_Main_ResizeViewCache();
5093 R_View_SetFrustum(NULL);
5094 R_View_WorldVisibility(r_refdef.view.useclipplane);
5095 R_View_UpdateEntityVisible();
5096 R_View_UpdateEntityLighting();
5099 void R_SetupView(qboolean allowwaterclippingplane)
5101 const float *customclipplane = NULL;
5103 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5105 // LordHavoc: couldn't figure out how to make this approach the
5106 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5107 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5108 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5109 dist = r_refdef.view.clipplane.dist;
5110 plane[0] = r_refdef.view.clipplane.normal[0];
5111 plane[1] = r_refdef.view.clipplane.normal[1];
5112 plane[2] = r_refdef.view.clipplane.normal[2];
5114 customclipplane = plane;
5117 if (!r_refdef.view.useperspective)
5118 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, -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);
5119 else if (vid.stencil && r_useinfinitefarclip.integer)
5120 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5122 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5123 R_SetViewport(&r_refdef.view.viewport);
5126 void R_EntityMatrix(const matrix4x4_t *matrix)
5128 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5130 gl_modelmatrixchanged = false;
5131 gl_modelmatrix = *matrix;
5132 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5133 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5134 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5135 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5137 switch(vid.renderpath)
5139 case RENDERPATH_D3D9:
5141 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5142 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5145 case RENDERPATH_D3D10:
5146 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5148 case RENDERPATH_D3D11:
5149 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5151 case RENDERPATH_GL13:
5152 case RENDERPATH_GL11:
5153 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5155 case RENDERPATH_SOFT:
5156 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5157 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5159 case RENDERPATH_GL20:
5160 case RENDERPATH_GLES2:
5161 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5162 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5168 void R_ResetViewRendering2D(void)
5170 r_viewport_t viewport;
5173 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5174 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);
5175 R_SetViewport(&viewport);
5176 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5177 GL_Color(1, 1, 1, 1);
5178 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5179 GL_BlendFunc(GL_ONE, GL_ZERO);
5180 GL_ScissorTest(false);
5181 GL_DepthMask(false);
5182 GL_DepthRange(0, 1);
5183 GL_DepthTest(false);
5184 GL_DepthFunc(GL_LEQUAL);
5185 R_EntityMatrix(&identitymatrix);
5186 R_Mesh_ResetTextureState();
5187 GL_PolygonOffset(0, 0);
5188 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5189 switch(vid.renderpath)
5191 case RENDERPATH_GL11:
5192 case RENDERPATH_GL13:
5193 case RENDERPATH_GL20:
5194 case RENDERPATH_GLES2:
5195 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5197 case RENDERPATH_D3D9:
5198 case RENDERPATH_D3D10:
5199 case RENDERPATH_D3D11:
5200 case RENDERPATH_SOFT:
5203 GL_CullFace(GL_NONE);
5206 void R_ResetViewRendering3D(void)
5211 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5212 GL_Color(1, 1, 1, 1);
5213 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5214 GL_BlendFunc(GL_ONE, GL_ZERO);
5215 GL_ScissorTest(true);
5217 GL_DepthRange(0, 1);
5219 GL_DepthFunc(GL_LEQUAL);
5220 R_EntityMatrix(&identitymatrix);
5221 R_Mesh_ResetTextureState();
5222 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5223 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5224 switch(vid.renderpath)
5226 case RENDERPATH_GL11:
5227 case RENDERPATH_GL13:
5228 case RENDERPATH_GL20:
5229 case RENDERPATH_GLES2:
5230 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5232 case RENDERPATH_D3D9:
5233 case RENDERPATH_D3D10:
5234 case RENDERPATH_D3D11:
5235 case RENDERPATH_SOFT:
5238 GL_CullFace(r_refdef.view.cullface_back);
5243 R_RenderView_UpdateViewVectors
5246 static void R_RenderView_UpdateViewVectors(void)
5248 // break apart the view matrix into vectors for various purposes
5249 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5250 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5251 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5252 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5253 // make an inverted copy of the view matrix for tracking sprites
5254 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5257 void R_RenderScene(void);
5258 void R_RenderWaterPlanes(void);
5260 static void R_Water_StartFrame(void)
5263 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5264 r_waterstate_waterplane_t *p;
5266 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5269 switch(vid.renderpath)
5271 case RENDERPATH_GL20:
5272 case RENDERPATH_D3D9:
5273 case RENDERPATH_D3D10:
5274 case RENDERPATH_D3D11:
5275 case RENDERPATH_SOFT:
5276 case RENDERPATH_GLES2:
5278 case RENDERPATH_GL13:
5279 case RENDERPATH_GL11:
5283 // set waterwidth and waterheight to the water resolution that will be
5284 // used (often less than the screen resolution for faster rendering)
5285 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5286 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5288 // calculate desired texture sizes
5289 // can't use water if the card does not support the texture size
5290 if (!r_water.integer || r_showsurfaces.integer)
5291 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5292 else if (vid.support.arb_texture_non_power_of_two)
5294 texturewidth = waterwidth;
5295 textureheight = waterheight;
5296 camerawidth = waterwidth;
5297 cameraheight = waterheight;
5301 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5302 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5303 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5304 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5307 // allocate textures as needed
5308 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5310 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5311 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5313 if (p->texture_refraction)
5314 R_FreeTexture(p->texture_refraction);
5315 p->texture_refraction = NULL;
5316 if (p->texture_reflection)
5317 R_FreeTexture(p->texture_reflection);
5318 p->texture_reflection = NULL;
5319 if (p->texture_camera)
5320 R_FreeTexture(p->texture_camera);
5321 p->texture_camera = NULL;
5323 memset(&r_waterstate, 0, sizeof(r_waterstate));
5324 r_waterstate.texturewidth = texturewidth;
5325 r_waterstate.textureheight = textureheight;
5326 r_waterstate.camerawidth = camerawidth;
5327 r_waterstate.cameraheight = cameraheight;
5330 if (r_waterstate.texturewidth)
5332 r_waterstate.enabled = true;
5334 // when doing a reduced render (HDR) we want to use a smaller area
5335 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5336 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5338 // set up variables that will be used in shader setup
5339 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5340 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5341 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5342 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5345 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5346 r_waterstate.numwaterplanes = 0;
5349 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5351 int triangleindex, planeindex;
5357 r_waterstate_waterplane_t *p;
5358 texture_t *t = R_GetCurrentTexture(surface->texture);
5360 // just use the first triangle with a valid normal for any decisions
5361 VectorClear(normal);
5362 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5364 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5365 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5366 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5367 TriangleNormal(vert[0], vert[1], vert[2], normal);
5368 if (VectorLength2(normal) >= 0.001)
5372 VectorCopy(normal, plane.normal);
5373 VectorNormalize(plane.normal);
5374 plane.dist = DotProduct(vert[0], plane.normal);
5375 PlaneClassify(&plane);
5376 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5378 // skip backfaces (except if nocullface is set)
5379 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5381 VectorNegate(plane.normal, plane.normal);
5383 PlaneClassify(&plane);
5387 // find a matching plane if there is one
5388 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5389 if(p->camera_entity == t->camera_entity)
5390 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5392 if (planeindex >= r_waterstate.maxwaterplanes)
5393 return; // nothing we can do, out of planes
5395 // if this triangle does not fit any known plane rendered this frame, add one
5396 if (planeindex >= r_waterstate.numwaterplanes)
5398 // store the new plane
5399 r_waterstate.numwaterplanes++;
5401 // clear materialflags and pvs
5402 p->materialflags = 0;
5403 p->pvsvalid = false;
5404 p->camera_entity = t->camera_entity;
5405 VectorCopy(surface->mins, p->mins);
5406 VectorCopy(surface->maxs, p->maxs);
5411 p->mins[0] = min(p->mins[0], surface->mins[0]);
5412 p->mins[1] = min(p->mins[1], surface->mins[1]);
5413 p->mins[2] = min(p->mins[2], surface->mins[2]);
5414 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5415 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5416 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5418 // merge this surface's materialflags into the waterplane
5419 p->materialflags |= t->currentmaterialflags;
5420 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5422 // merge this surface's PVS into the waterplane
5423 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5424 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5425 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5427 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5433 static void R_Water_ProcessPlanes(void)
5436 r_refdef_view_t originalview;
5437 r_refdef_view_t myview;
5439 r_waterstate_waterplane_t *p;
5442 originalview = r_refdef.view;
5444 // make sure enough textures are allocated
5445 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5447 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5449 if (!p->texture_refraction)
5450 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);
5451 if (!p->texture_refraction)
5454 else if (p->materialflags & MATERIALFLAG_CAMERA)
5456 if (!p->texture_camera)
5457 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);
5458 if (!p->texture_camera)
5462 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5464 if (!p->texture_reflection)
5465 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);
5466 if (!p->texture_reflection)
5472 r_refdef.view = originalview;
5473 r_refdef.view.showdebug = false;
5474 r_refdef.view.width = r_waterstate.waterwidth;
5475 r_refdef.view.height = r_waterstate.waterheight;
5476 r_refdef.view.useclipplane = true;
5477 myview = r_refdef.view;
5478 r_waterstate.renderingscene = true;
5479 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5481 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5483 r_refdef.view = myview;
5484 if(r_water_scissormode.integer)
5487 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5488 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5491 // render reflected scene and copy into texture
5492 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5493 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5494 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5495 r_refdef.view.clipplane = p->plane;
5497 // reverse the cullface settings for this render
5498 r_refdef.view.cullface_front = GL_FRONT;
5499 r_refdef.view.cullface_back = GL_BACK;
5500 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5502 r_refdef.view.usecustompvs = true;
5504 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5506 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5509 R_ResetViewRendering3D();
5510 R_ClearScreen(r_refdef.fogenabled);
5511 if(r_water_scissormode.integer & 2)
5512 R_View_UpdateWithScissor(myscissor);
5515 if(r_water_scissormode.integer & 1)
5516 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5519 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);
5522 // render the normal view scene and copy into texture
5523 // (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)
5524 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5526 r_refdef.view = myview;
5527 if(r_water_scissormode.integer)
5530 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5531 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5534 r_waterstate.renderingrefraction = true;
5536 r_refdef.view.clipplane = p->plane;
5537 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5538 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5540 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5542 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5543 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5544 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5545 R_RenderView_UpdateViewVectors();
5546 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5548 r_refdef.view.usecustompvs = true;
5549 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);
5553 PlaneClassify(&r_refdef.view.clipplane);
5555 R_ResetViewRendering3D();
5556 R_ClearScreen(r_refdef.fogenabled);
5557 if(r_water_scissormode.integer & 2)
5558 R_View_UpdateWithScissor(myscissor);
5561 if(r_water_scissormode.integer & 1)
5562 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5565 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);
5566 r_waterstate.renderingrefraction = false;
5568 else if (p->materialflags & MATERIALFLAG_CAMERA)
5570 r_refdef.view = myview;
5572 r_refdef.view.clipplane = p->plane;
5573 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5574 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5576 r_refdef.view.width = r_waterstate.camerawidth;
5577 r_refdef.view.height = r_waterstate.cameraheight;
5578 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5579 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5581 if(p->camera_entity)
5583 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5584 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5587 // note: all of the view is used for displaying... so
5588 // there is no use in scissoring
5590 // reverse the cullface settings for this render
5591 r_refdef.view.cullface_front = GL_FRONT;
5592 r_refdef.view.cullface_back = GL_BACK;
5593 // also reverse the view matrix
5594 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
5595 R_RenderView_UpdateViewVectors();
5596 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5598 r_refdef.view.usecustompvs = true;
5599 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);
5602 // camera needs no clipplane
5603 r_refdef.view.useclipplane = false;
5605 PlaneClassify(&r_refdef.view.clipplane);
5607 R_ResetViewRendering3D();
5608 R_ClearScreen(r_refdef.fogenabled);
5612 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);
5613 r_waterstate.renderingrefraction = false;
5617 r_waterstate.renderingscene = false;
5618 r_refdef.view = originalview;
5619 R_ResetViewRendering3D();
5620 R_ClearScreen(r_refdef.fogenabled);
5624 r_refdef.view = originalview;
5625 r_waterstate.renderingscene = false;
5626 Cvar_SetValueQuick(&r_water, 0);
5627 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5631 void R_Bloom_StartFrame(void)
5633 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5635 switch(vid.renderpath)
5637 case RENDERPATH_GL20:
5638 case RENDERPATH_D3D9:
5639 case RENDERPATH_D3D10:
5640 case RENDERPATH_D3D11:
5641 case RENDERPATH_SOFT:
5642 case RENDERPATH_GLES2:
5644 case RENDERPATH_GL13:
5645 case RENDERPATH_GL11:
5649 // set bloomwidth and bloomheight to the bloom resolution that will be
5650 // used (often less than the screen resolution for faster rendering)
5651 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5652 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5653 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5654 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5655 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5657 // calculate desired texture sizes
5658 if (vid.support.arb_texture_non_power_of_two)
5660 screentexturewidth = r_refdef.view.width;
5661 screentextureheight = r_refdef.view.height;
5662 bloomtexturewidth = r_bloomstate.bloomwidth;
5663 bloomtextureheight = r_bloomstate.bloomheight;
5667 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5668 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5669 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5670 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5673 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))
5675 Cvar_SetValueQuick(&r_hdr, 0);
5676 Cvar_SetValueQuick(&r_bloom, 0);
5677 Cvar_SetValueQuick(&r_motionblur, 0);
5678 Cvar_SetValueQuick(&r_damageblur, 0);
5681 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)))
5682 screentexturewidth = screentextureheight = 0;
5683 if (!r_hdr.integer && !r_bloom.integer)
5684 bloomtexturewidth = bloomtextureheight = 0;
5686 // allocate textures as needed
5687 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5689 if (r_bloomstate.texture_screen)
5690 R_FreeTexture(r_bloomstate.texture_screen);
5691 r_bloomstate.texture_screen = NULL;
5692 r_bloomstate.screentexturewidth = screentexturewidth;
5693 r_bloomstate.screentextureheight = screentextureheight;
5694 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5695 r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
5697 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5699 if (r_bloomstate.texture_bloom)
5700 R_FreeTexture(r_bloomstate.texture_bloom);
5701 r_bloomstate.texture_bloom = NULL;
5702 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5703 r_bloomstate.bloomtextureheight = bloomtextureheight;
5704 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5705 r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5708 // when doing a reduced render (HDR) we want to use a smaller area
5709 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5710 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5711 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5712 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5713 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5715 // set up a texcoord array for the full resolution screen image
5716 // (we have to keep this around to copy back during final render)
5717 r_bloomstate.screentexcoord2f[0] = 0;
5718 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5719 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5720 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5721 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5722 r_bloomstate.screentexcoord2f[5] = 0;
5723 r_bloomstate.screentexcoord2f[6] = 0;
5724 r_bloomstate.screentexcoord2f[7] = 0;
5726 // set up a texcoord array for the reduced resolution bloom image
5727 // (which will be additive blended over the screen image)
5728 r_bloomstate.bloomtexcoord2f[0] = 0;
5729 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5730 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5731 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5732 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5733 r_bloomstate.bloomtexcoord2f[5] = 0;
5734 r_bloomstate.bloomtexcoord2f[6] = 0;
5735 r_bloomstate.bloomtexcoord2f[7] = 0;
5737 switch(vid.renderpath)
5739 case RENDERPATH_GL11:
5740 case RENDERPATH_GL13:
5741 case RENDERPATH_GL20:
5742 case RENDERPATH_SOFT:
5743 case RENDERPATH_GLES2:
5745 case RENDERPATH_D3D9:
5746 case RENDERPATH_D3D10:
5747 case RENDERPATH_D3D11:
5750 for (i = 0;i < 4;i++)
5752 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5753 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5754 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5755 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5761 if (r_hdr.integer || r_bloom.integer)
5763 r_bloomstate.enabled = true;
5764 r_bloomstate.hdr = r_hdr.integer != 0;
5767 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);
5770 void R_Bloom_CopyBloomTexture(float colorscale)
5772 r_refdef.stats.bloom++;
5774 // scale down screen texture to the bloom texture size
5776 R_SetViewport(&r_bloomstate.viewport);
5777 GL_BlendFunc(GL_ONE, GL_ZERO);
5778 GL_Color(colorscale, colorscale, colorscale, 1);
5779 // 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...
5780 switch(vid.renderpath)
5782 case RENDERPATH_GL11:
5783 case RENDERPATH_GL13:
5784 case RENDERPATH_GL20:
5785 case RENDERPATH_SOFT:
5786 case RENDERPATH_GLES2:
5787 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5789 case RENDERPATH_D3D9:
5790 case RENDERPATH_D3D10:
5791 case RENDERPATH_D3D11:
5792 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5795 // TODO: do boxfilter scale-down in shader?
5796 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5797 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5798 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5800 // we now have a bloom image in the framebuffer
5801 // copy it into the bloom image texture for later processing
5802 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);
5803 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5806 void R_Bloom_CopyHDRTexture(void)
5808 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);
5809 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5812 void R_Bloom_MakeTexture(void)
5815 float xoffset, yoffset, r, brighten;
5817 r_refdef.stats.bloom++;
5819 R_ResetViewRendering2D();
5821 // we have a bloom image in the framebuffer
5823 R_SetViewport(&r_bloomstate.viewport);
5825 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5828 r = bound(0, r_bloom_colorexponent.value / x, 1);
5829 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5831 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5832 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5833 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5834 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5836 // copy the vertically blurred bloom view to a texture
5837 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);
5838 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5841 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5842 brighten = r_bloom_brighten.value;
5844 brighten *= r_hdr_range.value;
5845 brighten = sqrt(brighten);
5847 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5848 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5850 for (dir = 0;dir < 2;dir++)
5852 // blend on at multiple vertical offsets to achieve a vertical blur
5853 // TODO: do offset blends using GLSL
5854 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5855 GL_BlendFunc(GL_ONE, GL_ZERO);
5856 for (x = -range;x <= range;x++)
5858 if (!dir){xoffset = 0;yoffset = x;}
5859 else {xoffset = x;yoffset = 0;}
5860 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5861 yoffset /= (float)r_bloomstate.bloomtextureheight;
5862 // compute a texcoord array with the specified x and y offset
5863 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5864 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5865 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5866 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5867 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5868 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5869 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5870 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5871 // this r value looks like a 'dot' particle, fading sharply to
5872 // black at the edges
5873 // (probably not realistic but looks good enough)
5874 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5875 //r = brighten/(range*2+1);
5876 r = brighten / (range * 2 + 1);
5878 r *= (1 - x*x/(float)(range*range));
5879 GL_Color(r, r, r, 1);
5880 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5881 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5882 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5883 GL_BlendFunc(GL_ONE, GL_ONE);
5886 // copy the vertically blurred bloom view to a texture
5887 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);
5888 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5892 void R_HDR_RenderBloomTexture(void)
5894 int oldwidth, oldheight;
5895 float oldcolorscale;
5896 qboolean oldwaterstate;
5898 oldwaterstate = r_waterstate.enabled;
5899 oldcolorscale = r_refdef.view.colorscale;
5900 oldwidth = r_refdef.view.width;
5901 oldheight = r_refdef.view.height;
5902 r_refdef.view.width = r_bloomstate.bloomwidth;
5903 r_refdef.view.height = r_bloomstate.bloomheight;
5905 if(r_hdr.integer < 2)
5906 r_waterstate.enabled = false;
5908 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5909 // TODO: add exposure compensation features
5910 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5912 r_refdef.view.showdebug = false;
5913 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5915 R_ResetViewRendering3D();
5917 R_ClearScreen(r_refdef.fogenabled);
5918 if (r_timereport_active)
5919 R_TimeReport("HDRclear");
5922 if (r_timereport_active)
5923 R_TimeReport("visibility");
5925 // only do secondary renders with HDR if r_hdr is 2 or higher
5926 r_waterstate.numwaterplanes = 0;
5927 if (r_waterstate.enabled)
5928 R_RenderWaterPlanes();
5930 r_refdef.view.showdebug = true;
5932 r_waterstate.numwaterplanes = 0;
5934 R_ResetViewRendering2D();
5936 R_Bloom_CopyHDRTexture();
5937 R_Bloom_MakeTexture();
5939 // restore the view settings
5940 r_waterstate.enabled = oldwaterstate;
5941 r_refdef.view.width = oldwidth;
5942 r_refdef.view.height = oldheight;
5943 r_refdef.view.colorscale = oldcolorscale;
5945 R_ResetViewRendering3D();
5947 R_ClearScreen(r_refdef.fogenabled);
5948 if (r_timereport_active)
5949 R_TimeReport("viewclear");
5952 static void R_BlendView(void)
5954 unsigned int permutation;
5955 float uservecs[4][4];
5957 switch (vid.renderpath)
5959 case RENDERPATH_GL20:
5960 case RENDERPATH_D3D9:
5961 case RENDERPATH_D3D10:
5962 case RENDERPATH_D3D11:
5963 case RENDERPATH_SOFT:
5964 case RENDERPATH_GLES2:
5966 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5967 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5968 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5969 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5970 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5972 if (r_bloomstate.texture_screen)
5974 // make sure the buffer is available
5975 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5977 R_ResetViewRendering2D();
5979 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5981 // declare variables
5983 static float avgspeed;
5985 speed = VectorLength(cl.movement_velocity);
5987 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5988 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5990 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5991 speed = bound(0, speed, 1);
5992 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5994 // calculate values into a standard alpha
5995 cl.motionbluralpha = 1 - exp(-
5997 (r_motionblur.value * speed / 80)
5999 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6002 max(0.0001, cl.time - cl.oldtime) // fps independent
6005 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6006 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6008 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6010 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6011 GL_Color(1, 1, 1, cl.motionbluralpha);
6012 switch(vid.renderpath)
6014 case RENDERPATH_GL11:
6015 case RENDERPATH_GL13:
6016 case RENDERPATH_GL20:
6017 case RENDERPATH_SOFT:
6018 case RENDERPATH_GLES2:
6019 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6021 case RENDERPATH_D3D9:
6022 case RENDERPATH_D3D10:
6023 case RENDERPATH_D3D11:
6024 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6027 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6028 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6029 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6033 // copy view into the screen texture
6034 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);
6035 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6037 else if (!r_bloomstate.texture_bloom)
6039 // we may still have to do view tint...
6040 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6042 // apply a color tint to the whole view
6043 R_ResetViewRendering2D();
6044 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6045 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6046 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6047 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6048 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6050 break; // no screen processing, no bloom, skip it
6053 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6055 // render simple bloom effect
6056 // copy the screen and shrink it and darken it for the bloom process
6057 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6058 // make the bloom texture
6059 R_Bloom_MakeTexture();
6062 #if _MSC_VER >= 1400
6063 #define sscanf sscanf_s
6065 memset(uservecs, 0, sizeof(uservecs));
6066 if (r_glsl_postprocess_uservec1_enable.integer)
6067 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6068 if (r_glsl_postprocess_uservec2_enable.integer)
6069 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6070 if (r_glsl_postprocess_uservec3_enable.integer)
6071 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6072 if (r_glsl_postprocess_uservec4_enable.integer)
6073 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6075 R_ResetViewRendering2D();
6076 GL_Color(1, 1, 1, 1);
6077 GL_BlendFunc(GL_ONE, GL_ZERO);
6079 switch(vid.renderpath)
6081 case RENDERPATH_GL20:
6082 case RENDERPATH_GLES2:
6083 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6084 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6085 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6086 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6087 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6088 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]);
6089 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6090 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]);
6091 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]);
6092 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]);
6093 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]);
6094 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6095 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6096 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);
6098 case RENDERPATH_D3D9:
6100 // 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...
6101 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6102 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6103 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6104 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6105 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6106 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6107 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6108 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6109 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6110 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6111 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6112 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6113 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6114 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6117 case RENDERPATH_D3D10:
6118 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6120 case RENDERPATH_D3D11:
6121 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6123 case RENDERPATH_SOFT:
6124 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6125 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6126 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6127 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6128 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6129 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6130 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6131 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6132 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6133 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6134 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6135 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6136 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6137 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6142 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6143 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6145 case RENDERPATH_GL13:
6146 case RENDERPATH_GL11:
6147 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6149 // apply a color tint to the whole view
6150 R_ResetViewRendering2D();
6151 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6152 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6153 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6154 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6155 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6161 matrix4x4_t r_waterscrollmatrix;
6163 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6165 if (r_refdef.fog_density)
6167 r_refdef.fogcolor[0] = r_refdef.fog_red;
6168 r_refdef.fogcolor[1] = r_refdef.fog_green;
6169 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6171 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6172 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6173 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6174 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6178 VectorCopy(r_refdef.fogcolor, fogvec);
6179 // color.rgb *= ContrastBoost * SceneBrightness;
6180 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6181 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6182 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6183 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6188 void R_UpdateVariables(void)
6192 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6194 r_refdef.farclip = r_farclip_base.value;
6195 if (r_refdef.scene.worldmodel)
6196 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6197 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6199 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6200 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6201 r_refdef.polygonfactor = 0;
6202 r_refdef.polygonoffset = 0;
6203 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6204 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6206 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6207 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6208 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6209 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6210 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6211 if (FAKELIGHT_ENABLED)
6213 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6215 if (r_showsurfaces.integer)
6217 r_refdef.scene.rtworld = false;
6218 r_refdef.scene.rtworldshadows = false;
6219 r_refdef.scene.rtdlight = false;
6220 r_refdef.scene.rtdlightshadows = false;
6221 r_refdef.lightmapintensity = 0;
6224 if (gamemode == GAME_NEHAHRA)
6226 if (gl_fogenable.integer)
6228 r_refdef.oldgl_fogenable = true;
6229 r_refdef.fog_density = gl_fogdensity.value;
6230 r_refdef.fog_red = gl_fogred.value;
6231 r_refdef.fog_green = gl_foggreen.value;
6232 r_refdef.fog_blue = gl_fogblue.value;
6233 r_refdef.fog_alpha = 1;
6234 r_refdef.fog_start = 0;
6235 r_refdef.fog_end = gl_skyclip.value;
6236 r_refdef.fog_height = 1<<30;
6237 r_refdef.fog_fadedepth = 128;
6239 else if (r_refdef.oldgl_fogenable)
6241 r_refdef.oldgl_fogenable = false;
6242 r_refdef.fog_density = 0;
6243 r_refdef.fog_red = 0;
6244 r_refdef.fog_green = 0;
6245 r_refdef.fog_blue = 0;
6246 r_refdef.fog_alpha = 0;
6247 r_refdef.fog_start = 0;
6248 r_refdef.fog_end = 0;
6249 r_refdef.fog_height = 1<<30;
6250 r_refdef.fog_fadedepth = 128;
6254 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6255 r_refdef.fog_start = max(0, r_refdef.fog_start);
6256 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6258 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6260 if (r_refdef.fog_density && r_drawfog.integer)
6262 r_refdef.fogenabled = true;
6263 // this is the point where the fog reaches 0.9986 alpha, which we
6264 // consider a good enough cutoff point for the texture
6265 // (0.9986 * 256 == 255.6)
6266 if (r_fog_exp2.integer)
6267 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6269 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6270 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6271 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6272 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6273 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6274 R_BuildFogHeightTexture();
6275 // fog color was already set
6276 // update the fog texture
6277 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)
6278 R_BuildFogTexture();
6279 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6280 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6283 r_refdef.fogenabled = false;
6285 switch(vid.renderpath)
6287 case RENDERPATH_GL20:
6288 case RENDERPATH_D3D9:
6289 case RENDERPATH_D3D10:
6290 case RENDERPATH_D3D11:
6291 case RENDERPATH_SOFT:
6292 case RENDERPATH_GLES2:
6293 if(v_glslgamma.integer && !vid_gammatables_trivial)
6295 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6297 // build GLSL gamma texture
6298 #define RAMPWIDTH 256
6299 unsigned short ramp[RAMPWIDTH * 3];
6300 unsigned char rampbgr[RAMPWIDTH][4];
6303 r_texture_gammaramps_serial = vid_gammatables_serial;
6305 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6306 for(i = 0; i < RAMPWIDTH; ++i)
6308 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6309 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6310 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6313 if (r_texture_gammaramps)
6315 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6319 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6325 // remove GLSL gamma texture
6328 case RENDERPATH_GL13:
6329 case RENDERPATH_GL11:
6334 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6335 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6341 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6342 if( scenetype != r_currentscenetype ) {
6343 // store the old scenetype
6344 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6345 r_currentscenetype = scenetype;
6346 // move in the new scene
6347 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6356 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6358 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6359 if( scenetype == r_currentscenetype ) {
6360 return &r_refdef.scene;
6362 return &r_scenes_store[ scenetype ];
6371 int dpsoftrast_test;
6372 void R_RenderView(void)
6374 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6376 dpsoftrast_test = r_test.integer;
6378 if (r_timereport_active)
6379 R_TimeReport("start");
6380 r_textureframe++; // used only by R_GetCurrentTexture
6381 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6383 if(R_CompileShader_CheckStaticParms())
6386 if (!r_drawentities.integer)
6387 r_refdef.scene.numentities = 0;
6389 R_AnimCache_ClearCache();
6390 R_FrameData_NewFrame();
6392 /* adjust for stereo display */
6393 if(R_Stereo_Active())
6395 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);
6396 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6399 if (r_refdef.view.isoverlay)
6401 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6402 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6403 R_TimeReport("depthclear");
6405 r_refdef.view.showdebug = false;
6407 r_waterstate.enabled = false;
6408 r_waterstate.numwaterplanes = 0;
6412 r_refdef.view.matrix = originalmatrix;
6418 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6420 r_refdef.view.matrix = originalmatrix;
6421 return; //Host_Error ("R_RenderView: NULL worldmodel");
6424 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6426 R_RenderView_UpdateViewVectors();
6428 R_Shadow_UpdateWorldLightSelection();
6430 R_Bloom_StartFrame();
6431 R_Water_StartFrame();
6434 if (r_timereport_active)
6435 R_TimeReport("viewsetup");
6437 R_ResetViewRendering3D();
6439 if (r_refdef.view.clear || r_refdef.fogenabled)
6441 R_ClearScreen(r_refdef.fogenabled);
6442 if (r_timereport_active)
6443 R_TimeReport("viewclear");
6445 r_refdef.view.clear = true;
6447 // this produces a bloom texture to be used in R_BlendView() later
6448 if (r_hdr.integer && r_bloomstate.bloomwidth)
6450 R_HDR_RenderBloomTexture();
6451 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6452 r_textureframe++; // used only by R_GetCurrentTexture
6455 r_refdef.view.showdebug = true;
6458 if (r_timereport_active)
6459 R_TimeReport("visibility");
6461 r_waterstate.numwaterplanes = 0;
6462 if (r_waterstate.enabled)
6463 R_RenderWaterPlanes();
6466 r_waterstate.numwaterplanes = 0;
6469 if (r_timereport_active)
6470 R_TimeReport("blendview");
6472 GL_Scissor(0, 0, vid.width, vid.height);
6473 GL_ScissorTest(false);
6475 r_refdef.view.matrix = originalmatrix;
6480 void R_RenderWaterPlanes(void)
6482 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6484 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6485 if (r_timereport_active)
6486 R_TimeReport("waterworld");
6489 // don't let sound skip if going slow
6490 if (r_refdef.scene.extraupdate)
6493 R_DrawModelsAddWaterPlanes();
6494 if (r_timereport_active)
6495 R_TimeReport("watermodels");
6497 if (r_waterstate.numwaterplanes)
6499 R_Water_ProcessPlanes();
6500 if (r_timereport_active)
6501 R_TimeReport("waterscenes");
6505 extern void R_DrawLightningBeams (void);
6506 extern void VM_CL_AddPolygonsToMeshQueue (void);
6507 extern void R_DrawPortals (void);
6508 extern cvar_t cl_locs_show;
6509 static void R_DrawLocs(void);
6510 static void R_DrawEntityBBoxes(void);
6511 static void R_DrawModelDecals(void);
6512 extern void R_DrawModelShadows(void);
6513 extern void R_DrawModelShadowMaps(void);
6514 extern cvar_t cl_decals_newsystem;
6515 extern qboolean r_shadow_usingdeferredprepass;
6516 void R_RenderScene(void)
6518 qboolean shadowmapping = false;
6520 if (r_timereport_active)
6521 R_TimeReport("beginscene");
6523 r_refdef.stats.renders++;
6527 // don't let sound skip if going slow
6528 if (r_refdef.scene.extraupdate)
6531 R_MeshQueue_BeginScene();
6535 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);
6537 if (r_timereport_active)
6538 R_TimeReport("skystartframe");
6540 if (cl.csqc_vidvars.drawworld)
6542 // don't let sound skip if going slow
6543 if (r_refdef.scene.extraupdate)
6546 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6548 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6549 if (r_timereport_active)
6550 R_TimeReport("worldsky");
6553 if (R_DrawBrushModelsSky() && r_timereport_active)
6554 R_TimeReport("bmodelsky");
6556 if (skyrendermasked && skyrenderlater)
6558 // we have to force off the water clipping plane while rendering sky
6562 if (r_timereport_active)
6563 R_TimeReport("sky");
6567 R_AnimCache_CacheVisibleEntities();
6568 if (r_timereport_active)
6569 R_TimeReport("animation");
6571 R_Shadow_PrepareLights();
6572 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6573 R_Shadow_PrepareModelShadows();
6574 if (r_timereport_active)
6575 R_TimeReport("preparelights");
6577 if (R_Shadow_ShadowMappingEnabled())
6578 shadowmapping = true;
6580 if (r_shadow_usingdeferredprepass)
6581 R_Shadow_DrawPrepass();
6583 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6585 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6586 if (r_timereport_active)
6587 R_TimeReport("worlddepth");
6589 if (r_depthfirst.integer >= 2)
6591 R_DrawModelsDepth();
6592 if (r_timereport_active)
6593 R_TimeReport("modeldepth");
6596 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6598 R_DrawModelShadowMaps();
6599 R_ResetViewRendering3D();
6600 // don't let sound skip if going slow
6601 if (r_refdef.scene.extraupdate)
6605 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6607 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6608 if (r_timereport_active)
6609 R_TimeReport("world");
6612 // don't let sound skip if going slow
6613 if (r_refdef.scene.extraupdate)
6617 if (r_timereport_active)
6618 R_TimeReport("models");
6620 // don't let sound skip if going slow
6621 if (r_refdef.scene.extraupdate)
6624 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6626 R_DrawModelShadows();
6627 R_ResetViewRendering3D();
6628 // don't let sound skip if going slow
6629 if (r_refdef.scene.extraupdate)
6633 if (!r_shadow_usingdeferredprepass)
6635 R_Shadow_DrawLights();
6636 if (r_timereport_active)
6637 R_TimeReport("rtlights");
6640 // don't let sound skip if going slow
6641 if (r_refdef.scene.extraupdate)
6644 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6646 R_DrawModelShadows();
6647 R_ResetViewRendering3D();
6648 // don't let sound skip if going slow
6649 if (r_refdef.scene.extraupdate)
6653 if (cl.csqc_vidvars.drawworld)
6655 if (cl_decals_newsystem.integer)
6657 R_DrawModelDecals();
6658 if (r_timereport_active)
6659 R_TimeReport("modeldecals");
6664 if (r_timereport_active)
6665 R_TimeReport("decals");
6669 if (r_timereport_active)
6670 R_TimeReport("particles");
6673 if (r_timereport_active)
6674 R_TimeReport("explosions");
6676 R_DrawLightningBeams();
6677 if (r_timereport_active)
6678 R_TimeReport("lightning");
6681 VM_CL_AddPolygonsToMeshQueue();
6683 if (r_refdef.view.showdebug)
6685 if (cl_locs_show.integer)
6688 if (r_timereport_active)
6689 R_TimeReport("showlocs");
6692 if (r_drawportals.integer)
6695 if (r_timereport_active)
6696 R_TimeReport("portals");
6699 if (r_showbboxes.value > 0)
6701 R_DrawEntityBBoxes();
6702 if (r_timereport_active)
6703 R_TimeReport("bboxes");
6707 R_MeshQueue_RenderTransparent();
6708 if (r_timereport_active)
6709 R_TimeReport("drawtrans");
6711 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))
6713 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6714 if (r_timereport_active)
6715 R_TimeReport("worlddebug");
6716 R_DrawModelsDebug();
6717 if (r_timereport_active)
6718 R_TimeReport("modeldebug");
6721 if (cl.csqc_vidvars.drawworld)
6723 R_Shadow_DrawCoronas();
6724 if (r_timereport_active)
6725 R_TimeReport("coronas");
6730 GL_DepthTest(false);
6731 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6732 GL_Color(1, 1, 1, 1);
6733 qglBegin(GL_POLYGON);
6734 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6735 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6736 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6737 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6739 qglBegin(GL_POLYGON);
6740 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]);
6741 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]);
6742 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]);
6743 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]);
6745 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6749 // don't let sound skip if going slow
6750 if (r_refdef.scene.extraupdate)
6753 R_ResetViewRendering2D();
6756 static const unsigned short bboxelements[36] =
6766 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6769 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6771 RSurf_ActiveWorldEntity();
6773 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6774 GL_DepthMask(false);
6775 GL_DepthRange(0, 1);
6776 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6777 // R_Mesh_ResetTextureState();
6779 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6780 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6781 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6782 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6783 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6784 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6785 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6786 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6787 R_FillColors(color4f, 8, cr, cg, cb, ca);
6788 if (r_refdef.fogenabled)
6790 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6792 f1 = RSurf_FogVertex(v);
6794 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6795 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6796 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6799 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6800 R_Mesh_ResetTextureState();
6801 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6802 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6805 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6809 prvm_edict_t *edict;
6810 prvm_prog_t *prog_save = prog;
6812 // this function draws bounding boxes of server entities
6816 GL_CullFace(GL_NONE);
6817 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6821 for (i = 0;i < numsurfaces;i++)
6823 edict = PRVM_EDICT_NUM(surfacelist[i]);
6824 switch ((int)edict->fields.server->solid)
6826 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6827 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6828 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6829 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6830 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6831 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6833 color[3] *= r_showbboxes.value;
6834 color[3] = bound(0, color[3], 1);
6835 GL_DepthTest(!r_showdisabledepthtest.integer);
6836 GL_CullFace(r_refdef.view.cullface_front);
6837 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6843 static void R_DrawEntityBBoxes(void)
6846 prvm_edict_t *edict;
6848 prvm_prog_t *prog_save = prog;
6850 // this function draws bounding boxes of server entities
6856 for (i = 0;i < prog->num_edicts;i++)
6858 edict = PRVM_EDICT_NUM(i);
6859 if (edict->priv.server->free)
6861 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6862 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6864 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6866 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6867 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6873 static const int nomodelelement3i[24] =
6885 static const unsigned short nomodelelement3s[24] =
6897 static const float nomodelvertex3f[6*3] =
6907 static const float nomodelcolor4f[6*4] =
6909 0.0f, 0.0f, 0.5f, 1.0f,
6910 0.0f, 0.0f, 0.5f, 1.0f,
6911 0.0f, 0.5f, 0.0f, 1.0f,
6912 0.0f, 0.5f, 0.0f, 1.0f,
6913 0.5f, 0.0f, 0.0f, 1.0f,
6914 0.5f, 0.0f, 0.0f, 1.0f
6917 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6923 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);
6925 // this is only called once per entity so numsurfaces is always 1, and
6926 // surfacelist is always {0}, so this code does not handle batches
6928 if (rsurface.ent_flags & RENDER_ADDITIVE)
6930 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6931 GL_DepthMask(false);
6933 else if (rsurface.colormod[3] < 1)
6935 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6936 GL_DepthMask(false);
6940 GL_BlendFunc(GL_ONE, GL_ZERO);
6943 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6944 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6945 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6946 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6947 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6948 for (i = 0, c = color4f;i < 6;i++, c += 4)
6950 c[0] *= rsurface.colormod[0];
6951 c[1] *= rsurface.colormod[1];
6952 c[2] *= rsurface.colormod[2];
6953 c[3] *= rsurface.colormod[3];
6955 if (r_refdef.fogenabled)
6957 for (i = 0, c = color4f;i < 6;i++, c += 4)
6959 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6961 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6962 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6963 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6966 // R_Mesh_ResetTextureState();
6967 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6968 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6969 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6972 void R_DrawNoModel(entity_render_t *ent)
6975 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6976 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6977 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6979 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6982 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6984 vec3_t right1, right2, diff, normal;
6986 VectorSubtract (org2, org1, normal);
6988 // calculate 'right' vector for start
6989 VectorSubtract (r_refdef.view.origin, org1, diff);
6990 CrossProduct (normal, diff, right1);
6991 VectorNormalize (right1);
6993 // calculate 'right' vector for end
6994 VectorSubtract (r_refdef.view.origin, org2, diff);
6995 CrossProduct (normal, diff, right2);
6996 VectorNormalize (right2);
6998 vert[ 0] = org1[0] + width * right1[0];
6999 vert[ 1] = org1[1] + width * right1[1];
7000 vert[ 2] = org1[2] + width * right1[2];
7001 vert[ 3] = org1[0] - width * right1[0];
7002 vert[ 4] = org1[1] - width * right1[1];
7003 vert[ 5] = org1[2] - width * right1[2];
7004 vert[ 6] = org2[0] - width * right2[0];
7005 vert[ 7] = org2[1] - width * right2[1];
7006 vert[ 8] = org2[2] - width * right2[2];
7007 vert[ 9] = org2[0] + width * right2[0];
7008 vert[10] = org2[1] + width * right2[1];
7009 vert[11] = org2[2] + width * right2[2];
7012 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)
7014 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7015 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7016 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7017 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7018 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7019 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7020 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7021 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7022 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7023 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7024 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7025 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7028 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7033 VectorSet(v, x, y, z);
7034 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7035 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7037 if (i == mesh->numvertices)
7039 if (mesh->numvertices < mesh->maxvertices)
7041 VectorCopy(v, vertex3f);
7042 mesh->numvertices++;
7044 return mesh->numvertices;
7050 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7054 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7055 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7056 e = mesh->element3i + mesh->numtriangles * 3;
7057 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7059 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7060 if (mesh->numtriangles < mesh->maxtriangles)
7065 mesh->numtriangles++;
7067 element[1] = element[2];
7071 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7075 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7076 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7077 e = mesh->element3i + mesh->numtriangles * 3;
7078 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7080 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7081 if (mesh->numtriangles < mesh->maxtriangles)
7086 mesh->numtriangles++;
7088 element[1] = element[2];
7092 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7093 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7095 int planenum, planenum2;
7098 mplane_t *plane, *plane2;
7100 double temppoints[2][256*3];
7101 // figure out how large a bounding box we need to properly compute this brush
7103 for (w = 0;w < numplanes;w++)
7104 maxdist = max(maxdist, fabs(planes[w].dist));
7105 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7106 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7107 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7111 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7112 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7114 if (planenum2 == planenum)
7116 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);
7119 if (tempnumpoints < 3)
7121 // generate elements forming a triangle fan for this polygon
7122 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7126 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)
7128 texturelayer_t *layer;
7129 layer = t->currentlayers + t->currentnumlayers++;
7131 layer->depthmask = depthmask;
7132 layer->blendfunc1 = blendfunc1;
7133 layer->blendfunc2 = blendfunc2;
7134 layer->texture = texture;
7135 layer->texmatrix = *matrix;
7136 layer->color[0] = r;
7137 layer->color[1] = g;
7138 layer->color[2] = b;
7139 layer->color[3] = a;
7142 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7144 if(parms[0] == 0 && parms[1] == 0)
7146 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7147 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7152 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7155 index = parms[2] + r_refdef.scene.time * parms[3];
7156 index -= floor(index);
7157 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7160 case Q3WAVEFUNC_NONE:
7161 case Q3WAVEFUNC_NOISE:
7162 case Q3WAVEFUNC_COUNT:
7165 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7166 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7167 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7168 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7169 case Q3WAVEFUNC_TRIANGLE:
7171 f = index - floor(index);
7182 f = parms[0] + parms[1] * f;
7183 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7184 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7188 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7193 matrix4x4_t matrix, temp;
7194 switch(tcmod->tcmod)
7198 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7199 matrix = r_waterscrollmatrix;
7201 matrix = identitymatrix;
7203 case Q3TCMOD_ENTITYTRANSLATE:
7204 // this is used in Q3 to allow the gamecode to control texcoord
7205 // scrolling on the entity, which is not supported in darkplaces yet.
7206 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7208 case Q3TCMOD_ROTATE:
7209 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7210 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7211 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7214 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7216 case Q3TCMOD_SCROLL:
7217 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7219 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7220 w = (int) tcmod->parms[0];
7221 h = (int) tcmod->parms[1];
7222 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7224 idx = (int) floor(f * w * h);
7225 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7227 case Q3TCMOD_STRETCH:
7228 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7229 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7231 case Q3TCMOD_TRANSFORM:
7232 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7233 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7234 VectorSet(tcmat + 6, 0 , 0 , 1);
7235 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7236 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7238 case Q3TCMOD_TURBULENT:
7239 // this is handled in the RSurf_PrepareVertices function
7240 matrix = identitymatrix;
7244 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7247 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7249 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7250 char name[MAX_QPATH];
7251 skinframe_t *skinframe;
7252 unsigned char pixels[296*194];
7253 strlcpy(cache->name, skinname, sizeof(cache->name));
7254 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7255 if (developer_loading.integer)
7256 Con_Printf("loading %s\n", name);
7257 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7258 if (!skinframe || !skinframe->base)
7261 fs_offset_t filesize;
7263 f = FS_LoadFile(name, tempmempool, true, &filesize);
7266 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7267 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7271 cache->skinframe = skinframe;
7274 texture_t *R_GetCurrentTexture(texture_t *t)
7277 const entity_render_t *ent = rsurface.entity;
7278 dp_model_t *model = ent->model;
7279 q3shaderinfo_layer_tcmod_t *tcmod;
7281 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7282 return t->currentframe;
7283 t->update_lastrenderframe = r_textureframe;
7284 t->update_lastrenderentity = (void *)ent;
7286 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7287 t->camera_entity = ent->entitynumber;
7289 t->camera_entity = 0;
7291 // switch to an alternate material if this is a q1bsp animated material
7293 texture_t *texture = t;
7294 int s = rsurface.ent_skinnum;
7295 if ((unsigned int)s >= (unsigned int)model->numskins)
7297 if (model->skinscenes)
7299 if (model->skinscenes[s].framecount > 1)
7300 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7302 s = model->skinscenes[s].firstframe;
7305 t = t + s * model->num_surfaces;
7308 // use an alternate animation if the entity's frame is not 0,
7309 // and only if the texture has an alternate animation
7310 if (rsurface.ent_alttextures && t->anim_total[1])
7311 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7313 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7315 texture->currentframe = t;
7318 // update currentskinframe to be a qw skin or animation frame
7319 if (rsurface.ent_qwskin >= 0)
7321 i = rsurface.ent_qwskin;
7322 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7324 r_qwskincache_size = cl.maxclients;
7326 Mem_Free(r_qwskincache);
7327 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7329 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7330 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7331 t->currentskinframe = r_qwskincache[i].skinframe;
7332 if (t->currentskinframe == NULL)
7333 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7335 else if (t->numskinframes >= 2)
7336 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7337 if (t->backgroundnumskinframes >= 2)
7338 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7340 t->currentmaterialflags = t->basematerialflags;
7341 t->currentalpha = rsurface.colormod[3];
7342 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7343 t->currentalpha *= r_wateralpha.value;
7344 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7345 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7346 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7347 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7348 if (!(rsurface.ent_flags & RENDER_LIGHT))
7349 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7350 else if (FAKELIGHT_ENABLED)
7352 // no modellight if using fakelight for the map
7354 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7356 // pick a model lighting mode
7357 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7358 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7360 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7362 if (rsurface.ent_flags & RENDER_ADDITIVE)
7363 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7364 else if (t->currentalpha < 1)
7365 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7366 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7367 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7368 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7369 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7370 if (t->backgroundnumskinframes)
7371 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7372 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7374 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7375 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7378 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7379 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7380 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7382 // there is no tcmod
7383 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7385 t->currenttexmatrix = r_waterscrollmatrix;
7386 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7388 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7390 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7391 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7394 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7395 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7396 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7397 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7399 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7400 if (t->currentskinframe->qpixels)
7401 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7402 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7403 if (!t->basetexture)
7404 t->basetexture = r_texture_notexture;
7405 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7406 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7407 t->nmaptexture = t->currentskinframe->nmap;
7408 if (!t->nmaptexture)
7409 t->nmaptexture = r_texture_blanknormalmap;
7410 t->glosstexture = r_texture_black;
7411 t->glowtexture = t->currentskinframe->glow;
7412 t->fogtexture = t->currentskinframe->fog;
7413 t->reflectmasktexture = t->currentskinframe->reflect;
7414 if (t->backgroundnumskinframes)
7416 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7417 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7418 t->backgroundglosstexture = r_texture_black;
7419 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7420 if (!t->backgroundnmaptexture)
7421 t->backgroundnmaptexture = r_texture_blanknormalmap;
7425 t->backgroundbasetexture = r_texture_white;
7426 t->backgroundnmaptexture = r_texture_blanknormalmap;
7427 t->backgroundglosstexture = r_texture_black;
7428 t->backgroundglowtexture = NULL;
7430 t->specularpower = r_shadow_glossexponent.value;
7431 // TODO: store reference values for these in the texture?
7432 t->specularscale = 0;
7433 if (r_shadow_gloss.integer > 0)
7435 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7437 if (r_shadow_glossintensity.value > 0)
7439 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7440 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7441 t->specularscale = r_shadow_glossintensity.value;
7444 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7446 t->glosstexture = r_texture_white;
7447 t->backgroundglosstexture = r_texture_white;
7448 t->specularscale = r_shadow_gloss2intensity.value;
7449 t->specularpower = r_shadow_gloss2exponent.value;
7452 t->specularscale *= t->specularscalemod;
7453 t->specularpower *= t->specularpowermod;
7455 // lightmaps mode looks bad with dlights using actual texturing, so turn
7456 // off the colormap and glossmap, but leave the normalmap on as it still
7457 // accurately represents the shading involved
7458 if (gl_lightmaps.integer)
7460 t->basetexture = r_texture_grey128;
7461 t->pantstexture = r_texture_black;
7462 t->shirttexture = r_texture_black;
7463 t->nmaptexture = r_texture_blanknormalmap;
7464 t->glosstexture = r_texture_black;
7465 t->glowtexture = NULL;
7466 t->fogtexture = NULL;
7467 t->reflectmasktexture = NULL;
7468 t->backgroundbasetexture = NULL;
7469 t->backgroundnmaptexture = r_texture_blanknormalmap;
7470 t->backgroundglosstexture = r_texture_black;
7471 t->backgroundglowtexture = NULL;
7472 t->specularscale = 0;
7473 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7476 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7477 VectorClear(t->dlightcolor);
7478 t->currentnumlayers = 0;
7479 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7481 int blendfunc1, blendfunc2;
7483 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7485 blendfunc1 = GL_SRC_ALPHA;
7486 blendfunc2 = GL_ONE;
7488 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7490 blendfunc1 = GL_SRC_ALPHA;
7491 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7493 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7495 blendfunc1 = t->customblendfunc[0];
7496 blendfunc2 = t->customblendfunc[1];
7500 blendfunc1 = GL_ONE;
7501 blendfunc2 = GL_ZERO;
7503 // don't colormod evilblend textures
7504 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7505 VectorSet(t->lightmapcolor, 1, 1, 1);
7506 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7507 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7509 // fullbright is not affected by r_refdef.lightmapintensity
7510 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]);
7511 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7512 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]);
7513 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7514 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]);
7518 vec3_t ambientcolor;
7520 // set the color tint used for lights affecting this surface
7521 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7523 // q3bsp has no lightmap updates, so the lightstylevalue that
7524 // would normally be baked into the lightmap must be
7525 // applied to the color
7526 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7527 if (model->type == mod_brushq3)
7528 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7529 colorscale *= r_refdef.lightmapintensity;
7530 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7531 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7532 // basic lit geometry
7533 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]);
7534 // add pants/shirt if needed
7535 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7536 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]);
7537 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7538 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]);
7539 // now add ambient passes if needed
7540 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7542 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]);
7543 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7544 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]);
7545 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7546 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]);
7549 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7550 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]);
7551 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7553 // if this is opaque use alpha blend which will darken the earlier
7556 // if this is an alpha blended material, all the earlier passes
7557 // were darkened by fog already, so we only need to add the fog
7558 // color ontop through the fog mask texture
7560 // if this is an additive blended material, all the earlier passes
7561 // were darkened by fog already, and we should not add fog color
7562 // (because the background was not darkened, there is no fog color
7563 // that was lost behind it).
7564 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]);
7568 return t->currentframe;
7571 rsurfacestate_t rsurface;
7573 void RSurf_ActiveWorldEntity(void)
7575 dp_model_t *model = r_refdef.scene.worldmodel;
7576 //if (rsurface.entity == r_refdef.scene.worldentity)
7578 rsurface.entity = r_refdef.scene.worldentity;
7579 rsurface.skeleton = NULL;
7580 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7581 rsurface.ent_skinnum = 0;
7582 rsurface.ent_qwskin = -1;
7583 rsurface.ent_shadertime = 0;
7584 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7585 rsurface.matrix = identitymatrix;
7586 rsurface.inversematrix = identitymatrix;
7587 rsurface.matrixscale = 1;
7588 rsurface.inversematrixscale = 1;
7589 R_EntityMatrix(&identitymatrix);
7590 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7591 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7592 rsurface.fograngerecip = r_refdef.fograngerecip;
7593 rsurface.fogheightfade = r_refdef.fogheightfade;
7594 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7595 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7596 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7597 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7598 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7599 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7600 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7601 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7602 rsurface.colormod[3] = 1;
7603 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);
7604 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7605 rsurface.frameblend[0].lerp = 1;
7606 rsurface.ent_alttextures = false;
7607 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7608 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7609 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7610 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7611 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7612 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7613 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7614 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7615 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7616 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7617 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7618 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7619 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7620 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7621 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7622 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7624 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7625 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7627 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7628 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7630 rsurface.modelelement3i = model->surfmesh.data_element3i;
7631 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7632 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7633 rsurface.modelelement3s = model->surfmesh.data_element3s;
7634 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7635 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7636 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7637 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7638 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7639 rsurface.modelsurfaces = model->data_surfaces;
7640 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7641 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7642 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7643 rsurface.modelgeneratedvertex = false;
7644 rsurface.batchgeneratedvertex = false;
7645 rsurface.batchfirstvertex = 0;
7646 rsurface.batchnumvertices = 0;
7647 rsurface.batchfirsttriangle = 0;
7648 rsurface.batchnumtriangles = 0;
7649 rsurface.batchvertex3f = NULL;
7650 rsurface.batchvertex3f_vertexbuffer = NULL;
7651 rsurface.batchvertex3f_bufferoffset = 0;
7652 rsurface.batchsvector3f = NULL;
7653 rsurface.batchsvector3f_vertexbuffer = NULL;
7654 rsurface.batchsvector3f_bufferoffset = 0;
7655 rsurface.batchtvector3f = NULL;
7656 rsurface.batchtvector3f_vertexbuffer = NULL;
7657 rsurface.batchtvector3f_bufferoffset = 0;
7658 rsurface.batchnormal3f = NULL;
7659 rsurface.batchnormal3f_vertexbuffer = NULL;
7660 rsurface.batchnormal3f_bufferoffset = 0;
7661 rsurface.batchlightmapcolor4f = NULL;
7662 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7663 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7664 rsurface.batchtexcoordtexture2f = NULL;
7665 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7666 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7667 rsurface.batchtexcoordlightmap2f = NULL;
7668 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7669 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7670 rsurface.batchvertexmesh = NULL;
7671 rsurface.batchvertexmeshbuffer = NULL;
7672 rsurface.batchvertex3fbuffer = NULL;
7673 rsurface.batchelement3i = NULL;
7674 rsurface.batchelement3i_indexbuffer = NULL;
7675 rsurface.batchelement3i_bufferoffset = 0;
7676 rsurface.batchelement3s = NULL;
7677 rsurface.batchelement3s_indexbuffer = NULL;
7678 rsurface.batchelement3s_bufferoffset = 0;
7679 rsurface.passcolor4f = NULL;
7680 rsurface.passcolor4f_vertexbuffer = NULL;
7681 rsurface.passcolor4f_bufferoffset = 0;
7684 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7686 dp_model_t *model = ent->model;
7687 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7689 rsurface.entity = (entity_render_t *)ent;
7690 rsurface.skeleton = ent->skeleton;
7691 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7692 rsurface.ent_skinnum = ent->skinnum;
7693 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;
7694 rsurface.ent_shadertime = ent->shadertime;
7695 rsurface.ent_flags = ent->flags;
7696 rsurface.matrix = ent->matrix;
7697 rsurface.inversematrix = ent->inversematrix;
7698 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7699 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7700 R_EntityMatrix(&rsurface.matrix);
7701 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7702 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7703 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7704 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7705 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7706 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7707 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7708 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7709 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7710 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7711 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7712 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7713 rsurface.colormod[3] = ent->alpha;
7714 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7715 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7716 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7717 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7718 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7719 if (ent->model->brush.submodel && !prepass)
7721 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7722 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7724 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7726 if (ent->animcache_vertex3f)
7728 rsurface.modelvertex3f = ent->animcache_vertex3f;
7729 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7730 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7731 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7732 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7733 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7734 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7736 else if (wanttangents)
7738 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7739 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7740 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7741 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7742 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7743 rsurface.modelvertexmesh = NULL;
7744 rsurface.modelvertexmeshbuffer = NULL;
7745 rsurface.modelvertex3fbuffer = NULL;
7747 else if (wantnormals)
7749 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7750 rsurface.modelsvector3f = NULL;
7751 rsurface.modeltvector3f = NULL;
7752 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7754 rsurface.modelvertexmesh = NULL;
7755 rsurface.modelvertexmeshbuffer = NULL;
7756 rsurface.modelvertex3fbuffer = NULL;
7760 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7761 rsurface.modelsvector3f = NULL;
7762 rsurface.modeltvector3f = NULL;
7763 rsurface.modelnormal3f = NULL;
7764 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7765 rsurface.modelvertexmesh = NULL;
7766 rsurface.modelvertexmeshbuffer = NULL;
7767 rsurface.modelvertex3fbuffer = NULL;
7769 rsurface.modelvertex3f_vertexbuffer = 0;
7770 rsurface.modelvertex3f_bufferoffset = 0;
7771 rsurface.modelsvector3f_vertexbuffer = 0;
7772 rsurface.modelsvector3f_bufferoffset = 0;
7773 rsurface.modeltvector3f_vertexbuffer = 0;
7774 rsurface.modeltvector3f_bufferoffset = 0;
7775 rsurface.modelnormal3f_vertexbuffer = 0;
7776 rsurface.modelnormal3f_bufferoffset = 0;
7777 rsurface.modelgeneratedvertex = true;
7781 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7782 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7783 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7784 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7785 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7787 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7788 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7790 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7791 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7793 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7794 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7795 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7796 rsurface.modelgeneratedvertex = false;
7798 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7799 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7800 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7801 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7802 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7804 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7805 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7806 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7807 rsurface.modelelement3i = model->surfmesh.data_element3i;
7808 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7809 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7810 rsurface.modelelement3s = model->surfmesh.data_element3s;
7811 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7812 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7813 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7814 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7815 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7816 rsurface.modelsurfaces = model->data_surfaces;
7817 rsurface.batchgeneratedvertex = false;
7818 rsurface.batchfirstvertex = 0;
7819 rsurface.batchnumvertices = 0;
7820 rsurface.batchfirsttriangle = 0;
7821 rsurface.batchnumtriangles = 0;
7822 rsurface.batchvertex3f = NULL;
7823 rsurface.batchvertex3f_vertexbuffer = NULL;
7824 rsurface.batchvertex3f_bufferoffset = 0;
7825 rsurface.batchsvector3f = NULL;
7826 rsurface.batchsvector3f_vertexbuffer = NULL;
7827 rsurface.batchsvector3f_bufferoffset = 0;
7828 rsurface.batchtvector3f = NULL;
7829 rsurface.batchtvector3f_vertexbuffer = NULL;
7830 rsurface.batchtvector3f_bufferoffset = 0;
7831 rsurface.batchnormal3f = NULL;
7832 rsurface.batchnormal3f_vertexbuffer = NULL;
7833 rsurface.batchnormal3f_bufferoffset = 0;
7834 rsurface.batchlightmapcolor4f = NULL;
7835 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7836 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7837 rsurface.batchtexcoordtexture2f = NULL;
7838 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7839 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7840 rsurface.batchtexcoordlightmap2f = NULL;
7841 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7842 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7843 rsurface.batchvertexmesh = NULL;
7844 rsurface.batchvertexmeshbuffer = NULL;
7845 rsurface.batchvertex3fbuffer = NULL;
7846 rsurface.batchelement3i = NULL;
7847 rsurface.batchelement3i_indexbuffer = NULL;
7848 rsurface.batchelement3i_bufferoffset = 0;
7849 rsurface.batchelement3s = NULL;
7850 rsurface.batchelement3s_indexbuffer = NULL;
7851 rsurface.batchelement3s_bufferoffset = 0;
7852 rsurface.passcolor4f = NULL;
7853 rsurface.passcolor4f_vertexbuffer = NULL;
7854 rsurface.passcolor4f_bufferoffset = 0;
7857 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)
7859 rsurface.entity = r_refdef.scene.worldentity;
7860 rsurface.skeleton = NULL;
7861 rsurface.ent_skinnum = 0;
7862 rsurface.ent_qwskin = -1;
7863 rsurface.ent_shadertime = shadertime;
7864 rsurface.ent_flags = entflags;
7865 rsurface.modelnumvertices = numvertices;
7866 rsurface.modelnumtriangles = numtriangles;
7867 rsurface.matrix = *matrix;
7868 rsurface.inversematrix = *inversematrix;
7869 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7870 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7871 R_EntityMatrix(&rsurface.matrix);
7872 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7873 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7874 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7875 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7876 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7877 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7878 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7879 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7880 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7881 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7882 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7883 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7884 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);
7885 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7886 rsurface.frameblend[0].lerp = 1;
7887 rsurface.ent_alttextures = false;
7888 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7889 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7892 rsurface.modelvertex3f = (float *)vertex3f;
7893 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7894 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7895 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7897 else if (wantnormals)
7899 rsurface.modelvertex3f = (float *)vertex3f;
7900 rsurface.modelsvector3f = NULL;
7901 rsurface.modeltvector3f = NULL;
7902 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7906 rsurface.modelvertex3f = (float *)vertex3f;
7907 rsurface.modelsvector3f = NULL;
7908 rsurface.modeltvector3f = NULL;
7909 rsurface.modelnormal3f = NULL;
7911 rsurface.modelvertexmesh = NULL;
7912 rsurface.modelvertexmeshbuffer = NULL;
7913 rsurface.modelvertex3fbuffer = NULL;
7914 rsurface.modelvertex3f_vertexbuffer = 0;
7915 rsurface.modelvertex3f_bufferoffset = 0;
7916 rsurface.modelsvector3f_vertexbuffer = 0;
7917 rsurface.modelsvector3f_bufferoffset = 0;
7918 rsurface.modeltvector3f_vertexbuffer = 0;
7919 rsurface.modeltvector3f_bufferoffset = 0;
7920 rsurface.modelnormal3f_vertexbuffer = 0;
7921 rsurface.modelnormal3f_bufferoffset = 0;
7922 rsurface.modelgeneratedvertex = true;
7923 rsurface.modellightmapcolor4f = (float *)color4f;
7924 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7925 rsurface.modellightmapcolor4f_bufferoffset = 0;
7926 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7927 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7928 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7929 rsurface.modeltexcoordlightmap2f = NULL;
7930 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7931 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7932 rsurface.modelelement3i = (int *)element3i;
7933 rsurface.modelelement3i_indexbuffer = NULL;
7934 rsurface.modelelement3i_bufferoffset = 0;
7935 rsurface.modelelement3s = (unsigned short *)element3s;
7936 rsurface.modelelement3s_indexbuffer = NULL;
7937 rsurface.modelelement3s_bufferoffset = 0;
7938 rsurface.modellightmapoffsets = NULL;
7939 rsurface.modelsurfaces = NULL;
7940 rsurface.batchgeneratedvertex = false;
7941 rsurface.batchfirstvertex = 0;
7942 rsurface.batchnumvertices = 0;
7943 rsurface.batchfirsttriangle = 0;
7944 rsurface.batchnumtriangles = 0;
7945 rsurface.batchvertex3f = NULL;
7946 rsurface.batchvertex3f_vertexbuffer = NULL;
7947 rsurface.batchvertex3f_bufferoffset = 0;
7948 rsurface.batchsvector3f = NULL;
7949 rsurface.batchsvector3f_vertexbuffer = NULL;
7950 rsurface.batchsvector3f_bufferoffset = 0;
7951 rsurface.batchtvector3f = NULL;
7952 rsurface.batchtvector3f_vertexbuffer = NULL;
7953 rsurface.batchtvector3f_bufferoffset = 0;
7954 rsurface.batchnormal3f = NULL;
7955 rsurface.batchnormal3f_vertexbuffer = NULL;
7956 rsurface.batchnormal3f_bufferoffset = 0;
7957 rsurface.batchlightmapcolor4f = NULL;
7958 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7959 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7960 rsurface.batchtexcoordtexture2f = NULL;
7961 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7962 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7963 rsurface.batchtexcoordlightmap2f = NULL;
7964 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7965 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7966 rsurface.batchvertexmesh = NULL;
7967 rsurface.batchvertexmeshbuffer = NULL;
7968 rsurface.batchvertex3fbuffer = NULL;
7969 rsurface.batchelement3i = NULL;
7970 rsurface.batchelement3i_indexbuffer = NULL;
7971 rsurface.batchelement3i_bufferoffset = 0;
7972 rsurface.batchelement3s = NULL;
7973 rsurface.batchelement3s_indexbuffer = NULL;
7974 rsurface.batchelement3s_bufferoffset = 0;
7975 rsurface.passcolor4f = NULL;
7976 rsurface.passcolor4f_vertexbuffer = NULL;
7977 rsurface.passcolor4f_bufferoffset = 0;
7979 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7981 if ((wantnormals || wanttangents) && !normal3f)
7983 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7984 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7986 if (wanttangents && !svector3f)
7988 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7989 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7990 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7995 float RSurf_FogPoint(const float *v)
7997 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
7998 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
7999 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8000 float FogHeightFade = r_refdef.fogheightfade;
8002 unsigned int fogmasktableindex;
8003 if (r_refdef.fogplaneviewabove)
8004 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8006 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8007 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8008 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8011 float RSurf_FogVertex(const float *v)
8013 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8014 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8015 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8016 float FogHeightFade = rsurface.fogheightfade;
8018 unsigned int fogmasktableindex;
8019 if (r_refdef.fogplaneviewabove)
8020 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8022 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8023 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8024 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8027 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8030 for (i = 0;i < numelements;i++)
8031 outelement3i[i] = inelement3i[i] + adjust;
8034 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8035 extern cvar_t gl_vbo;
8036 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8044 int surfacefirsttriangle;
8045 int surfacenumtriangles;
8046 int surfacefirstvertex;
8047 int surfaceendvertex;
8048 int surfacenumvertices;
8049 int batchnumvertices;
8050 int batchnumtriangles;
8054 qboolean dynamicvertex;
8058 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8060 q3shaderinfo_deform_t *deform;
8061 const msurface_t *surface, *firstsurface;
8062 r_vertexmesh_t *vertexmesh;
8063 if (!texturenumsurfaces)
8065 // find vertex range of this surface batch
8067 firstsurface = texturesurfacelist[0];
8068 firsttriangle = firstsurface->num_firsttriangle;
8069 batchnumvertices = 0;
8070 batchnumtriangles = 0;
8071 firstvertex = endvertex = firstsurface->num_firstvertex;
8072 for (i = 0;i < texturenumsurfaces;i++)
8074 surface = texturesurfacelist[i];
8075 if (surface != firstsurface + i)
8077 surfacefirstvertex = surface->num_firstvertex;
8078 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8079 surfacenumvertices = surface->num_vertices;
8080 surfacenumtriangles = surface->num_triangles;
8081 if (firstvertex > surfacefirstvertex)
8082 firstvertex = surfacefirstvertex;
8083 if (endvertex < surfaceendvertex)
8084 endvertex = surfaceendvertex;
8085 batchnumvertices += surfacenumvertices;
8086 batchnumtriangles += surfacenumtriangles;
8089 // we now know the vertex range used, and if there are any gaps in it
8090 rsurface.batchfirstvertex = firstvertex;
8091 rsurface.batchnumvertices = endvertex - firstvertex;
8092 rsurface.batchfirsttriangle = firsttriangle;
8093 rsurface.batchnumtriangles = batchnumtriangles;
8095 // this variable holds flags for which properties have been updated that
8096 // may require regenerating vertexmesh array...
8099 // check if any dynamic vertex processing must occur
8100 dynamicvertex = false;
8102 // if there is a chance of animated vertex colors, it's a dynamic batch
8103 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8105 dynamicvertex = true;
8106 batchneed |= BATCHNEED_NOGAPS;
8107 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8110 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8112 switch (deform->deform)
8115 case Q3DEFORM_PROJECTIONSHADOW:
8116 case Q3DEFORM_TEXT0:
8117 case Q3DEFORM_TEXT1:
8118 case Q3DEFORM_TEXT2:
8119 case Q3DEFORM_TEXT3:
8120 case Q3DEFORM_TEXT4:
8121 case Q3DEFORM_TEXT5:
8122 case Q3DEFORM_TEXT6:
8123 case Q3DEFORM_TEXT7:
8126 case Q3DEFORM_AUTOSPRITE:
8127 dynamicvertex = true;
8128 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8129 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8131 case Q3DEFORM_AUTOSPRITE2:
8132 dynamicvertex = true;
8133 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8134 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8136 case Q3DEFORM_NORMAL:
8137 dynamicvertex = true;
8138 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8139 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8142 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8143 break; // if wavefunc is a nop, ignore this transform
8144 dynamicvertex = true;
8145 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8146 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8148 case Q3DEFORM_BULGE:
8149 dynamicvertex = true;
8150 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8151 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8154 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8155 break; // if wavefunc is a nop, ignore this transform
8156 dynamicvertex = true;
8157 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8158 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8162 switch(rsurface.texture->tcgen.tcgen)
8165 case Q3TCGEN_TEXTURE:
8167 case Q3TCGEN_LIGHTMAP:
8168 dynamicvertex = true;
8169 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8170 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8172 case Q3TCGEN_VECTOR:
8173 dynamicvertex = true;
8174 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8175 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8177 case Q3TCGEN_ENVIRONMENT:
8178 dynamicvertex = true;
8179 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8180 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8183 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8185 dynamicvertex = true;
8186 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8187 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8190 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8192 dynamicvertex = true;
8193 batchneed |= BATCHNEED_NOGAPS;
8194 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8197 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8199 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8200 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8201 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8202 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8203 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8204 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8205 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8208 // when the model data has no vertex buffer (dynamic mesh), we need to
8210 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8211 batchneed |= BATCHNEED_NOGAPS;
8213 // if needsupdate, we have to do a dynamic vertex batch for sure
8214 if (needsupdate & batchneed)
8215 dynamicvertex = true;
8217 // see if we need to build vertexmesh from arrays
8218 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8219 dynamicvertex = true;
8221 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8222 // also some drivers strongly dislike firstvertex
8223 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8224 dynamicvertex = true;
8226 rsurface.batchvertex3f = rsurface.modelvertex3f;
8227 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8228 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8229 rsurface.batchsvector3f = rsurface.modelsvector3f;
8230 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8231 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8232 rsurface.batchtvector3f = rsurface.modeltvector3f;
8233 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8234 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8235 rsurface.batchnormal3f = rsurface.modelnormal3f;
8236 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8237 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8238 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8239 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8240 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8241 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8242 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8243 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8244 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8245 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8246 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8247 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8248 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8249 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8250 rsurface.batchelement3i = rsurface.modelelement3i;
8251 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8252 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8253 rsurface.batchelement3s = rsurface.modelelement3s;
8254 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8255 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8257 // if any dynamic vertex processing has to occur in software, we copy the
8258 // entire surface list together before processing to rebase the vertices
8259 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8261 // if any gaps exist and we do not have a static vertex buffer, we have to
8262 // copy the surface list together to avoid wasting upload bandwidth on the
8263 // vertices in the gaps.
8265 // if gaps exist and we have a static vertex buffer, we still have to
8266 // combine the index buffer ranges into one dynamic index buffer.
8268 // in all cases we end up with data that can be drawn in one call.
8272 // static vertex data, just set pointers...
8273 rsurface.batchgeneratedvertex = false;
8274 // if there are gaps, we want to build a combined index buffer,
8275 // otherwise use the original static buffer with an appropriate offset
8278 // build a new triangle elements array for this batch
8279 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8280 rsurface.batchfirsttriangle = 0;
8282 for (i = 0;i < texturenumsurfaces;i++)
8284 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8285 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8286 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8287 numtriangles += surfacenumtriangles;
8289 rsurface.batchelement3i_indexbuffer = NULL;
8290 rsurface.batchelement3i_bufferoffset = 0;
8291 rsurface.batchelement3s = NULL;
8292 rsurface.batchelement3s_indexbuffer = NULL;
8293 rsurface.batchelement3s_bufferoffset = 0;
8294 if (endvertex <= 65536)
8296 // make a 16bit (unsigned short) index array if possible
8297 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8298 for (i = 0;i < numtriangles*3;i++)
8299 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8305 // something needs software processing, do it for real...
8306 // we only directly handle separate array data in this case and then
8307 // generate interleaved data if needed...
8308 rsurface.batchgeneratedvertex = true;
8310 // now copy the vertex data into a combined array and make an index array
8311 // (this is what Quake3 does all the time)
8312 //if (gaps || rsurface.batchfirstvertex)
8314 rsurface.batchvertex3fbuffer = NULL;
8315 rsurface.batchvertexmesh = NULL;
8316 rsurface.batchvertexmeshbuffer = NULL;
8317 rsurface.batchvertex3f = NULL;
8318 rsurface.batchvertex3f_vertexbuffer = NULL;
8319 rsurface.batchvertex3f_bufferoffset = 0;
8320 rsurface.batchsvector3f = NULL;
8321 rsurface.batchsvector3f_vertexbuffer = NULL;
8322 rsurface.batchsvector3f_bufferoffset = 0;
8323 rsurface.batchtvector3f = NULL;
8324 rsurface.batchtvector3f_vertexbuffer = NULL;
8325 rsurface.batchtvector3f_bufferoffset = 0;
8326 rsurface.batchnormal3f = NULL;
8327 rsurface.batchnormal3f_vertexbuffer = NULL;
8328 rsurface.batchnormal3f_bufferoffset = 0;
8329 rsurface.batchlightmapcolor4f = NULL;
8330 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8331 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8332 rsurface.batchtexcoordtexture2f = NULL;
8333 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8334 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8335 rsurface.batchtexcoordlightmap2f = NULL;
8336 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8337 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8338 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8339 rsurface.batchelement3i_indexbuffer = NULL;
8340 rsurface.batchelement3i_bufferoffset = 0;
8341 rsurface.batchelement3s = NULL;
8342 rsurface.batchelement3s_indexbuffer = NULL;
8343 rsurface.batchelement3s_bufferoffset = 0;
8344 // we'll only be setting up certain arrays as needed
8345 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8346 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8347 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8348 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8349 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8350 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8351 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8353 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8354 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8356 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8357 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8358 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8359 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8360 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8361 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8364 for (i = 0;i < texturenumsurfaces;i++)
8366 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8367 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8368 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8369 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8370 // copy only the data requested
8371 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8372 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8373 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8375 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8376 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8377 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8378 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8379 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8381 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8382 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8384 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8385 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8386 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8387 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8388 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8389 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8391 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8392 numvertices += surfacenumvertices;
8393 numtriangles += surfacenumtriangles;
8396 // generate a 16bit index array as well if possible
8397 // (in general, dynamic batches fit)
8398 if (numvertices <= 65536)
8400 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8401 for (i = 0;i < numtriangles*3;i++)
8402 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8405 // since we've copied everything, the batch now starts at 0
8406 rsurface.batchfirstvertex = 0;
8407 rsurface.batchnumvertices = batchnumvertices;
8408 rsurface.batchfirsttriangle = 0;
8409 rsurface.batchnumtriangles = batchnumtriangles;
8412 // q1bsp surfaces rendered in vertex color mode have to have colors
8413 // calculated based on lightstyles
8414 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8416 // generate color arrays for the surfaces in this list
8421 const unsigned char *lm;
8422 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8423 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8424 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8426 for (i = 0;i < texturenumsurfaces;i++)
8428 surface = texturesurfacelist[i];
8429 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8430 surfacenumvertices = surface->num_vertices;
8431 if (surface->lightmapinfo->samples)
8433 for (j = 0;j < surfacenumvertices;j++)
8435 lm = surface->lightmapinfo->samples + offsets[j];
8436 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8437 VectorScale(lm, scale, c);
8438 if (surface->lightmapinfo->styles[1] != 255)
8440 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8442 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8443 VectorMA(c, scale, lm, c);
8444 if (surface->lightmapinfo->styles[2] != 255)
8447 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8448 VectorMA(c, scale, lm, c);
8449 if (surface->lightmapinfo->styles[3] != 255)
8452 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8453 VectorMA(c, scale, lm, c);
8460 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);
8466 for (j = 0;j < surfacenumvertices;j++)
8468 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8475 // if vertices are deformed (sprite flares and things in maps, possibly
8476 // water waves, bulges and other deformations), modify the copied vertices
8478 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8480 switch (deform->deform)
8483 case Q3DEFORM_PROJECTIONSHADOW:
8484 case Q3DEFORM_TEXT0:
8485 case Q3DEFORM_TEXT1:
8486 case Q3DEFORM_TEXT2:
8487 case Q3DEFORM_TEXT3:
8488 case Q3DEFORM_TEXT4:
8489 case Q3DEFORM_TEXT5:
8490 case Q3DEFORM_TEXT6:
8491 case Q3DEFORM_TEXT7:
8494 case Q3DEFORM_AUTOSPRITE:
8495 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8496 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8497 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8498 VectorNormalize(newforward);
8499 VectorNormalize(newright);
8500 VectorNormalize(newup);
8501 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8502 // rsurface.batchvertex3f_vertexbuffer = NULL;
8503 // rsurface.batchvertex3f_bufferoffset = 0;
8504 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8505 // rsurface.batchsvector3f_vertexbuffer = NULL;
8506 // rsurface.batchsvector3f_bufferoffset = 0;
8507 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8508 // rsurface.batchtvector3f_vertexbuffer = NULL;
8509 // rsurface.batchtvector3f_bufferoffset = 0;
8510 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8511 // rsurface.batchnormal3f_vertexbuffer = NULL;
8512 // rsurface.batchnormal3f_bufferoffset = 0;
8513 // a single autosprite surface can contain multiple sprites...
8514 for (j = 0;j < batchnumvertices - 3;j += 4)
8516 VectorClear(center);
8517 for (i = 0;i < 4;i++)
8518 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8519 VectorScale(center, 0.25f, center);
8520 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8521 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8522 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8523 for (i = 0;i < 4;i++)
8525 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8526 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8529 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8530 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8531 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);
8533 case Q3DEFORM_AUTOSPRITE2:
8534 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8535 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8536 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8537 VectorNormalize(newforward);
8538 VectorNormalize(newright);
8539 VectorNormalize(newup);
8540 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8541 // rsurface.batchvertex3f_vertexbuffer = NULL;
8542 // rsurface.batchvertex3f_bufferoffset = 0;
8544 const float *v1, *v2;
8554 memset(shortest, 0, sizeof(shortest));
8555 // a single autosprite surface can contain multiple sprites...
8556 for (j = 0;j < batchnumvertices - 3;j += 4)
8558 VectorClear(center);
8559 for (i = 0;i < 4;i++)
8560 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8561 VectorScale(center, 0.25f, center);
8562 // find the two shortest edges, then use them to define the
8563 // axis vectors for rotating around the central axis
8564 for (i = 0;i < 6;i++)
8566 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8567 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8568 l = VectorDistance2(v1, v2);
8569 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8571 l += (1.0f / 1024.0f);
8572 if (shortest[0].length2 > l || i == 0)
8574 shortest[1] = shortest[0];
8575 shortest[0].length2 = l;
8576 shortest[0].v1 = v1;
8577 shortest[0].v2 = v2;
8579 else if (shortest[1].length2 > l || i == 1)
8581 shortest[1].length2 = l;
8582 shortest[1].v1 = v1;
8583 shortest[1].v2 = v2;
8586 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8587 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8588 // this calculates the right vector from the shortest edge
8589 // and the up vector from the edge midpoints
8590 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8591 VectorNormalize(right);
8592 VectorSubtract(end, start, up);
8593 VectorNormalize(up);
8594 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8595 VectorSubtract(rsurface.localvieworigin, center, forward);
8596 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8597 VectorNegate(forward, forward);
8598 VectorReflect(forward, 0, up, forward);
8599 VectorNormalize(forward);
8600 CrossProduct(up, forward, newright);
8601 VectorNormalize(newright);
8602 // rotate the quad around the up axis vector, this is made
8603 // especially easy by the fact we know the quad is flat,
8604 // so we only have to subtract the center position and
8605 // measure distance along the right vector, and then
8606 // multiply that by the newright vector and add back the
8608 // we also need to subtract the old position to undo the
8609 // displacement from the center, which we do with a
8610 // DotProduct, the subtraction/addition of center is also
8611 // optimized into DotProducts here
8612 l = DotProduct(right, center);
8613 for (i = 0;i < 4;i++)
8615 v1 = rsurface.batchvertex3f + 3*(j+i);
8616 f = DotProduct(right, v1) - l;
8617 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8621 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8623 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8624 // rsurface.batchnormal3f_vertexbuffer = NULL;
8625 // rsurface.batchnormal3f_bufferoffset = 0;
8626 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8628 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8630 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8631 // rsurface.batchsvector3f_vertexbuffer = NULL;
8632 // rsurface.batchsvector3f_bufferoffset = 0;
8633 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8634 // rsurface.batchtvector3f_vertexbuffer = NULL;
8635 // rsurface.batchtvector3f_bufferoffset = 0;
8636 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);
8639 case Q3DEFORM_NORMAL:
8640 // deform the normals to make reflections wavey
8641 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8642 rsurface.batchnormal3f_vertexbuffer = NULL;
8643 rsurface.batchnormal3f_bufferoffset = 0;
8644 for (j = 0;j < batchnumvertices;j++)
8647 float *normal = rsurface.batchnormal3f + 3*j;
8648 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8649 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8650 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]);
8651 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]);
8652 VectorNormalize(normal);
8654 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8656 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8657 // rsurface.batchsvector3f_vertexbuffer = NULL;
8658 // rsurface.batchsvector3f_bufferoffset = 0;
8659 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8660 // rsurface.batchtvector3f_vertexbuffer = NULL;
8661 // rsurface.batchtvector3f_bufferoffset = 0;
8662 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);
8666 // deform vertex array to make wavey water and flags and such
8667 waveparms[0] = deform->waveparms[0];
8668 waveparms[1] = deform->waveparms[1];
8669 waveparms[2] = deform->waveparms[2];
8670 waveparms[3] = deform->waveparms[3];
8671 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8672 break; // if wavefunc is a nop, don't make a dynamic vertex array
8673 // this is how a divisor of vertex influence on deformation
8674 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8675 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8676 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8677 // rsurface.batchvertex3f_vertexbuffer = NULL;
8678 // rsurface.batchvertex3f_bufferoffset = 0;
8679 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8680 // rsurface.batchnormal3f_vertexbuffer = NULL;
8681 // rsurface.batchnormal3f_bufferoffset = 0;
8682 for (j = 0;j < batchnumvertices;j++)
8684 // if the wavefunc depends on time, evaluate it per-vertex
8687 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8688 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8690 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8692 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8693 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8694 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8696 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8697 // rsurface.batchsvector3f_vertexbuffer = NULL;
8698 // rsurface.batchsvector3f_bufferoffset = 0;
8699 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8700 // rsurface.batchtvector3f_vertexbuffer = NULL;
8701 // rsurface.batchtvector3f_bufferoffset = 0;
8702 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);
8705 case Q3DEFORM_BULGE:
8706 // deform vertex array to make the surface have moving bulges
8707 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8708 // rsurface.batchvertex3f_vertexbuffer = NULL;
8709 // rsurface.batchvertex3f_bufferoffset = 0;
8710 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8711 // rsurface.batchnormal3f_vertexbuffer = NULL;
8712 // rsurface.batchnormal3f_bufferoffset = 0;
8713 for (j = 0;j < batchnumvertices;j++)
8715 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8716 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8718 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8719 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8720 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8722 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8723 // rsurface.batchsvector3f_vertexbuffer = NULL;
8724 // rsurface.batchsvector3f_bufferoffset = 0;
8725 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8726 // rsurface.batchtvector3f_vertexbuffer = NULL;
8727 // rsurface.batchtvector3f_bufferoffset = 0;
8728 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);
8732 // deform vertex array
8733 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8734 break; // if wavefunc is a nop, don't make a dynamic vertex array
8735 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8736 VectorScale(deform->parms, scale, waveparms);
8737 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8738 // rsurface.batchvertex3f_vertexbuffer = NULL;
8739 // rsurface.batchvertex3f_bufferoffset = 0;
8740 for (j = 0;j < batchnumvertices;j++)
8741 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8746 // generate texcoords based on the chosen texcoord source
8747 switch(rsurface.texture->tcgen.tcgen)
8750 case Q3TCGEN_TEXTURE:
8752 case Q3TCGEN_LIGHTMAP:
8753 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8754 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8755 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8756 if (rsurface.batchtexcoordlightmap2f)
8757 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8759 case Q3TCGEN_VECTOR:
8760 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8761 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8762 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8763 for (j = 0;j < batchnumvertices;j++)
8765 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8766 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8769 case Q3TCGEN_ENVIRONMENT:
8770 // make environment reflections using a spheremap
8771 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8772 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8773 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8774 for (j = 0;j < batchnumvertices;j++)
8776 // identical to Q3A's method, but executed in worldspace so
8777 // carried models can be shiny too
8779 float viewer[3], d, reflected[3], worldreflected[3];
8781 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8782 // VectorNormalize(viewer);
8784 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8786 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8787 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8788 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8789 // note: this is proportinal to viewer, so we can normalize later
8791 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8792 VectorNormalize(worldreflected);
8794 // note: this sphere map only uses world x and z!
8795 // so positive and negative y will LOOK THE SAME.
8796 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8797 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8801 // the only tcmod that needs software vertex processing is turbulent, so
8802 // check for it here and apply the changes if needed
8803 // and we only support that as the first one
8804 // (handling a mixture of turbulent and other tcmods would be problematic
8805 // without punting it entirely to a software path)
8806 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8808 amplitude = rsurface.texture->tcmods[0].parms[1];
8809 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8810 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8811 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8812 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8813 for (j = 0;j < batchnumvertices;j++)
8815 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);
8816 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8820 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8822 // convert the modified arrays to vertex structs
8823 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8824 // rsurface.batchvertexmeshbuffer = NULL;
8825 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8826 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8827 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8828 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8829 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8830 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8831 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8833 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8835 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8836 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8839 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8840 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8841 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8842 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8843 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8844 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8845 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8846 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8847 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8851 void RSurf_DrawBatch(void)
8853 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8854 // through the pipeline, killing it earlier in the pipeline would have
8855 // per-surface overhead rather than per-batch overhead, so it's best to
8856 // reject it here, before it hits glDraw.
8857 if (rsurface.batchnumtriangles == 0)
8860 // batch debugging code
8861 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8867 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8868 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8871 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8873 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8875 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8876 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);
8883 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);
8886 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8888 // pick the closest matching water plane
8889 int planeindex, vertexindex, bestplaneindex = -1;
8893 r_waterstate_waterplane_t *p;
8894 qboolean prepared = false;
8896 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8898 if(p->camera_entity != rsurface.texture->camera_entity)
8903 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8905 if(rsurface.batchnumvertices == 0)
8908 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8910 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8911 d += fabs(PlaneDiff(vert, &p->plane));
8913 if (bestd > d || bestplaneindex < 0)
8916 bestplaneindex = planeindex;
8919 return bestplaneindex;
8920 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8921 // this situation though, as it might be better to render single larger
8922 // batches with useless stuff (backface culled for example) than to
8923 // render multiple smaller batches
8926 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8929 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8930 rsurface.passcolor4f_vertexbuffer = 0;
8931 rsurface.passcolor4f_bufferoffset = 0;
8932 for (i = 0;i < rsurface.batchnumvertices;i++)
8933 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8936 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8943 if (rsurface.passcolor4f)
8945 // generate color arrays
8946 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8947 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8948 rsurface.passcolor4f_vertexbuffer = 0;
8949 rsurface.passcolor4f_bufferoffset = 0;
8950 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)
8952 f = RSurf_FogVertex(v);
8961 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8962 rsurface.passcolor4f_vertexbuffer = 0;
8963 rsurface.passcolor4f_bufferoffset = 0;
8964 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8966 f = RSurf_FogVertex(v);
8975 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8982 if (!rsurface.passcolor4f)
8984 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8985 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8986 rsurface.passcolor4f_vertexbuffer = 0;
8987 rsurface.passcolor4f_bufferoffset = 0;
8988 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)
8990 f = RSurf_FogVertex(v);
8991 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8992 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8993 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
8998 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9003 if (!rsurface.passcolor4f)
9005 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9006 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9007 rsurface.passcolor4f_vertexbuffer = 0;
9008 rsurface.passcolor4f_bufferoffset = 0;
9009 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9018 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9023 if (!rsurface.passcolor4f)
9025 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9026 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9027 rsurface.passcolor4f_vertexbuffer = 0;
9028 rsurface.passcolor4f_bufferoffset = 0;
9029 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9031 c2[0] = c[0] + r_refdef.scene.ambient;
9032 c2[1] = c[1] + r_refdef.scene.ambient;
9033 c2[2] = c[2] + r_refdef.scene.ambient;
9038 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9041 rsurface.passcolor4f = NULL;
9042 rsurface.passcolor4f_vertexbuffer = 0;
9043 rsurface.passcolor4f_bufferoffset = 0;
9044 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9045 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9046 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9047 GL_Color(r, g, b, a);
9048 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9052 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9054 // TODO: optimize applyfog && applycolor case
9055 // just apply fog if necessary, and tint the fog color array if necessary
9056 rsurface.passcolor4f = NULL;
9057 rsurface.passcolor4f_vertexbuffer = 0;
9058 rsurface.passcolor4f_bufferoffset = 0;
9059 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9060 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9061 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9062 GL_Color(r, g, b, a);
9066 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9069 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9070 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9071 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9072 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9073 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9074 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9075 GL_Color(r, g, b, a);
9079 static void RSurf_DrawBatch_GL11_ClampColor(void)
9084 if (!rsurface.passcolor4f)
9086 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9088 c2[0] = bound(0.0f, c1[0], 1.0f);
9089 c2[1] = bound(0.0f, c1[1], 1.0f);
9090 c2[2] = bound(0.0f, c1[2], 1.0f);
9091 c2[3] = bound(0.0f, c1[3], 1.0f);
9095 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9105 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9106 rsurface.passcolor4f_vertexbuffer = 0;
9107 rsurface.passcolor4f_bufferoffset = 0;
9108 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)
9110 f = -DotProduct(r_refdef.view.forward, n);
9112 f = f * 0.85 + 0.15; // work around so stuff won't get black
9113 f *= r_refdef.lightmapintensity;
9114 Vector4Set(c, f, f, f, 1);
9118 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9120 RSurf_DrawBatch_GL11_ApplyFakeLight();
9121 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9122 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9123 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9124 GL_Color(r, g, b, a);
9128 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9136 vec3_t ambientcolor;
9137 vec3_t diffusecolor;
9141 VectorCopy(rsurface.modellight_lightdir, lightdir);
9142 f = 0.5f * r_refdef.lightmapintensity;
9143 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9144 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9145 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9146 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9147 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9148 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9150 if (VectorLength2(diffusecolor) > 0)
9152 // q3-style directional shading
9153 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9154 rsurface.passcolor4f_vertexbuffer = 0;
9155 rsurface.passcolor4f_bufferoffset = 0;
9156 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)
9158 if ((f = DotProduct(n, lightdir)) > 0)
9159 VectorMA(ambientcolor, f, diffusecolor, c);
9161 VectorCopy(ambientcolor, c);
9168 *applycolor = false;
9172 *r = ambientcolor[0];
9173 *g = ambientcolor[1];
9174 *b = ambientcolor[2];
9175 rsurface.passcolor4f = NULL;
9176 rsurface.passcolor4f_vertexbuffer = 0;
9177 rsurface.passcolor4f_bufferoffset = 0;
9181 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9183 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9184 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9185 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9186 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9187 GL_Color(r, g, b, a);
9191 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9197 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9199 f = 1 - RSurf_FogVertex(v);
9207 void RSurf_SetupDepthAndCulling(void)
9209 // submodels are biased to avoid z-fighting with world surfaces that they
9210 // may be exactly overlapping (avoids z-fighting artifacts on certain
9211 // doors and things in Quake maps)
9212 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9213 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9214 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9215 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9218 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9220 // transparent sky would be ridiculous
9221 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9223 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9224 skyrenderlater = true;
9225 RSurf_SetupDepthAndCulling();
9227 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9228 // skymasking on them, and Quake3 never did sky masking (unlike
9229 // software Quake and software Quake2), so disable the sky masking
9230 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9231 // and skymasking also looks very bad when noclipping outside the
9232 // level, so don't use it then either.
9233 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9235 R_Mesh_ResetTextureState();
9236 if (skyrendermasked)
9238 R_SetupShader_DepthOrShadow();
9239 // depth-only (masking)
9240 GL_ColorMask(0,0,0,0);
9241 // just to make sure that braindead drivers don't draw
9242 // anything despite that colormask...
9243 GL_BlendFunc(GL_ZERO, GL_ONE);
9244 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9245 if (rsurface.batchvertex3fbuffer)
9246 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9248 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9252 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9254 GL_BlendFunc(GL_ONE, GL_ZERO);
9255 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9256 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9257 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9260 if (skyrendermasked)
9261 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9263 R_Mesh_ResetTextureState();
9264 GL_Color(1, 1, 1, 1);
9267 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9268 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9269 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9271 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9275 // render screenspace normalmap to texture
9277 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9282 // bind lightmap texture
9284 // water/refraction/reflection/camera surfaces have to be handled specially
9285 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9287 int start, end, startplaneindex;
9288 for (start = 0;start < texturenumsurfaces;start = end)
9290 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9291 if(startplaneindex < 0)
9293 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9294 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9298 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9300 // now that we have a batch using the same planeindex, render it
9301 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9303 // render water or distortion background
9305 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));
9307 // blend surface on top
9308 GL_DepthMask(false);
9309 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9312 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9314 // render surface with reflection texture as input
9315 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9316 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));
9323 // render surface batch normally
9324 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9325 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9329 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9331 // OpenGL 1.3 path - anything not completely ancient
9332 qboolean applycolor;
9335 const texturelayer_t *layer;
9336 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);
9337 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9339 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9342 int layertexrgbscale;
9343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9345 if (layerindex == 0)
9349 GL_AlphaTest(false);
9350 GL_DepthFunc(GL_EQUAL);
9353 GL_DepthMask(layer->depthmask && writedepth);
9354 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9355 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9357 layertexrgbscale = 4;
9358 VectorScale(layer->color, 0.25f, layercolor);
9360 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9362 layertexrgbscale = 2;
9363 VectorScale(layer->color, 0.5f, layercolor);
9367 layertexrgbscale = 1;
9368 VectorScale(layer->color, 1.0f, layercolor);
9370 layercolor[3] = layer->color[3];
9371 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9372 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9373 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9374 switch (layer->type)
9376 case TEXTURELAYERTYPE_LITTEXTURE:
9377 // single-pass lightmapped texture with 2x rgbscale
9378 R_Mesh_TexBind(0, r_texture_white);
9379 R_Mesh_TexMatrix(0, NULL);
9380 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9381 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9382 R_Mesh_TexBind(1, layer->texture);
9383 R_Mesh_TexMatrix(1, &layer->texmatrix);
9384 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9385 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9386 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9387 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9388 else if (FAKELIGHT_ENABLED)
9389 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9390 else if (rsurface.uselightmaptexture)
9391 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9393 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9395 case TEXTURELAYERTYPE_TEXTURE:
9396 // singletexture unlit texture with transparency support
9397 R_Mesh_TexBind(0, layer->texture);
9398 R_Mesh_TexMatrix(0, &layer->texmatrix);
9399 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9400 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9401 R_Mesh_TexBind(1, 0);
9402 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9403 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9405 case TEXTURELAYERTYPE_FOG:
9406 // singletexture fogging
9409 R_Mesh_TexBind(0, layer->texture);
9410 R_Mesh_TexMatrix(0, &layer->texmatrix);
9411 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9412 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9416 R_Mesh_TexBind(0, 0);
9417 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9419 R_Mesh_TexBind(1, 0);
9420 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9421 // generate a color array for the fog pass
9422 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9423 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9427 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9430 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9432 GL_DepthFunc(GL_LEQUAL);
9433 GL_AlphaTest(false);
9437 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9439 // OpenGL 1.1 - crusty old voodoo path
9442 const texturelayer_t *layer;
9443 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);
9444 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9446 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9448 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9450 if (layerindex == 0)
9454 GL_AlphaTest(false);
9455 GL_DepthFunc(GL_EQUAL);
9458 GL_DepthMask(layer->depthmask && writedepth);
9459 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9460 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9461 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9462 switch (layer->type)
9464 case TEXTURELAYERTYPE_LITTEXTURE:
9465 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9467 // two-pass lit texture with 2x rgbscale
9468 // first the lightmap pass
9469 R_Mesh_TexBind(0, r_texture_white);
9470 R_Mesh_TexMatrix(0, NULL);
9471 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9472 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9473 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9474 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9475 else if (FAKELIGHT_ENABLED)
9476 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9477 else if (rsurface.uselightmaptexture)
9478 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9480 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9481 // then apply the texture to it
9482 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9483 R_Mesh_TexBind(0, layer->texture);
9484 R_Mesh_TexMatrix(0, &layer->texmatrix);
9485 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9486 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9487 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);
9491 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9492 R_Mesh_TexBind(0, layer->texture);
9493 R_Mesh_TexMatrix(0, &layer->texmatrix);
9494 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9495 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9496 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9497 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);
9499 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);
9502 case TEXTURELAYERTYPE_TEXTURE:
9503 // singletexture unlit texture with transparency support
9504 R_Mesh_TexBind(0, layer->texture);
9505 R_Mesh_TexMatrix(0, &layer->texmatrix);
9506 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9507 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9508 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);
9510 case TEXTURELAYERTYPE_FOG:
9511 // singletexture fogging
9514 R_Mesh_TexBind(0, layer->texture);
9515 R_Mesh_TexMatrix(0, &layer->texmatrix);
9516 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9517 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9521 R_Mesh_TexBind(0, 0);
9522 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9524 // generate a color array for the fog pass
9525 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9526 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9530 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9533 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9535 GL_DepthFunc(GL_LEQUAL);
9536 GL_AlphaTest(false);
9540 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9544 r_vertexgeneric_t *batchvertex;
9547 // R_Mesh_ResetTextureState();
9548 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9550 if(rsurface.texture && rsurface.texture->currentskinframe)
9552 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9553 c[3] *= rsurface.texture->currentalpha;
9563 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9565 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9566 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9567 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9570 // brighten it up (as texture value 127 means "unlit")
9571 c[0] *= 2 * r_refdef.view.colorscale;
9572 c[1] *= 2 * r_refdef.view.colorscale;
9573 c[2] *= 2 * r_refdef.view.colorscale;
9575 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9576 c[3] *= r_wateralpha.value;
9578 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9580 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9581 GL_DepthMask(false);
9583 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9585 GL_BlendFunc(GL_ONE, GL_ONE);
9586 GL_DepthMask(false);
9588 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9590 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9591 GL_DepthMask(false);
9593 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9595 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9596 GL_DepthMask(false);
9600 GL_BlendFunc(GL_ONE, GL_ZERO);
9601 GL_DepthMask(writedepth);
9604 if (r_showsurfaces.integer == 3)
9606 rsurface.passcolor4f = NULL;
9608 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9610 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9612 rsurface.passcolor4f = NULL;
9613 rsurface.passcolor4f_vertexbuffer = 0;
9614 rsurface.passcolor4f_bufferoffset = 0;
9616 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9618 qboolean applycolor = true;
9621 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9623 r_refdef.lightmapintensity = 1;
9624 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9625 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9627 else if (FAKELIGHT_ENABLED)
9629 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9631 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9632 RSurf_DrawBatch_GL11_ApplyFakeLight();
9633 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9637 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9639 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9640 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9641 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9644 if(!rsurface.passcolor4f)
9645 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9647 RSurf_DrawBatch_GL11_ApplyAmbient();
9648 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9649 if(r_refdef.fogenabled)
9650 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9651 RSurf_DrawBatch_GL11_ClampColor();
9653 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9654 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9657 else if (!r_refdef.view.showdebug)
9659 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9660 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9661 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9663 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9664 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9666 R_Mesh_PrepareVertices_Generic_Unlock();
9669 else if (r_showsurfaces.integer == 4)
9671 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9672 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9673 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9675 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9676 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9677 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9679 R_Mesh_PrepareVertices_Generic_Unlock();
9682 else if (r_showsurfaces.integer == 2)
9685 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9686 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9687 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9689 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9690 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9691 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9692 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9693 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9694 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9695 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9697 R_Mesh_PrepareVertices_Generic_Unlock();
9698 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9702 int texturesurfaceindex;
9704 const msurface_t *surface;
9705 float surfacecolor4f[4];
9706 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9707 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9709 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9711 surface = texturesurfacelist[texturesurfaceindex];
9712 k = (int)(((size_t)surface) / sizeof(msurface_t));
9713 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9714 for (j = 0;j < surface->num_vertices;j++)
9716 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9717 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9721 R_Mesh_PrepareVertices_Generic_Unlock();
9726 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9729 RSurf_SetupDepthAndCulling();
9730 if (r_showsurfaces.integer)
9732 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9735 switch (vid.renderpath)
9737 case RENDERPATH_GL20:
9738 case RENDERPATH_D3D9:
9739 case RENDERPATH_D3D10:
9740 case RENDERPATH_D3D11:
9741 case RENDERPATH_SOFT:
9742 case RENDERPATH_GLES2:
9743 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9745 case RENDERPATH_GL13:
9746 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9748 case RENDERPATH_GL11:
9749 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9755 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9758 RSurf_SetupDepthAndCulling();
9759 if (r_showsurfaces.integer)
9761 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9764 switch (vid.renderpath)
9766 case RENDERPATH_GL20:
9767 case RENDERPATH_D3D9:
9768 case RENDERPATH_D3D10:
9769 case RENDERPATH_D3D11:
9770 case RENDERPATH_SOFT:
9771 case RENDERPATH_GLES2:
9772 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9774 case RENDERPATH_GL13:
9775 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9777 case RENDERPATH_GL11:
9778 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9784 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9787 int texturenumsurfaces, endsurface;
9789 const msurface_t *surface;
9790 #define MAXBATCH_TRANSPARENTSURFACES 256
9791 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9793 // if the model is static it doesn't matter what value we give for
9794 // wantnormals and wanttangents, so this logic uses only rules applicable
9795 // to a model, knowing that they are meaningless otherwise
9796 if (ent == r_refdef.scene.worldentity)
9797 RSurf_ActiveWorldEntity();
9798 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9799 RSurf_ActiveModelEntity(ent, false, false, false);
9802 switch (vid.renderpath)
9804 case RENDERPATH_GL20:
9805 case RENDERPATH_D3D9:
9806 case RENDERPATH_D3D10:
9807 case RENDERPATH_D3D11:
9808 case RENDERPATH_SOFT:
9809 case RENDERPATH_GLES2:
9810 RSurf_ActiveModelEntity(ent, true, true, false);
9812 case RENDERPATH_GL13:
9813 case RENDERPATH_GL11:
9814 RSurf_ActiveModelEntity(ent, true, false, false);
9819 if (r_transparentdepthmasking.integer)
9821 qboolean setup = false;
9822 for (i = 0;i < numsurfaces;i = j)
9825 surface = rsurface.modelsurfaces + surfacelist[i];
9826 texture = surface->texture;
9827 rsurface.texture = R_GetCurrentTexture(texture);
9828 rsurface.lightmaptexture = NULL;
9829 rsurface.deluxemaptexture = NULL;
9830 rsurface.uselightmaptexture = false;
9831 // scan ahead until we find a different texture
9832 endsurface = min(i + 1024, numsurfaces);
9833 texturenumsurfaces = 0;
9834 texturesurfacelist[texturenumsurfaces++] = surface;
9835 for (;j < endsurface;j++)
9837 surface = rsurface.modelsurfaces + surfacelist[j];
9838 if (texture != surface->texture)
9840 texturesurfacelist[texturenumsurfaces++] = surface;
9842 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9844 // render the range of surfaces as depth
9848 GL_ColorMask(0,0,0,0);
9851 GL_BlendFunc(GL_ONE, GL_ZERO);
9853 // R_Mesh_ResetTextureState();
9854 R_SetupShader_DepthOrShadow();
9856 RSurf_SetupDepthAndCulling();
9857 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9858 if (rsurface.batchvertex3fbuffer)
9859 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9861 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9865 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9868 for (i = 0;i < numsurfaces;i = j)
9871 surface = rsurface.modelsurfaces + surfacelist[i];
9872 texture = surface->texture;
9873 rsurface.texture = R_GetCurrentTexture(texture);
9874 // scan ahead until we find a different texture
9875 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9876 texturenumsurfaces = 0;
9877 texturesurfacelist[texturenumsurfaces++] = surface;
9878 if(FAKELIGHT_ENABLED)
9880 rsurface.lightmaptexture = NULL;
9881 rsurface.deluxemaptexture = NULL;
9882 rsurface.uselightmaptexture = false;
9883 for (;j < endsurface;j++)
9885 surface = rsurface.modelsurfaces + surfacelist[j];
9886 if (texture != surface->texture)
9888 texturesurfacelist[texturenumsurfaces++] = surface;
9893 rsurface.lightmaptexture = surface->lightmaptexture;
9894 rsurface.deluxemaptexture = surface->deluxemaptexture;
9895 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9896 for (;j < endsurface;j++)
9898 surface = rsurface.modelsurfaces + surfacelist[j];
9899 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9901 texturesurfacelist[texturenumsurfaces++] = surface;
9904 // render the range of surfaces
9905 if (ent == r_refdef.scene.worldentity)
9906 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9908 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9910 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9913 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9915 // transparent surfaces get pushed off into the transparent queue
9916 int surfacelistindex;
9917 const msurface_t *surface;
9918 vec3_t tempcenter, center;
9919 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9921 surface = texturesurfacelist[surfacelistindex];
9922 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9923 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9924 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9925 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9926 if (queueentity->transparent_offset) // transparent offset
9928 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9929 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9930 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9932 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9936 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9938 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9940 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9942 RSurf_SetupDepthAndCulling();
9943 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9944 if (rsurface.batchvertex3fbuffer)
9945 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9947 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9951 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9953 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9956 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9959 if (!rsurface.texture->currentnumlayers)
9961 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9962 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9964 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9966 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9967 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9968 else if (!rsurface.texture->currentnumlayers)
9970 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9972 // in the deferred case, transparent surfaces were queued during prepass
9973 if (!r_shadow_usingdeferredprepass)
9974 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9978 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9979 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9984 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9988 R_FrameData_SetMark();
9989 // break the surface list down into batches by texture and use of lightmapping
9990 for (i = 0;i < numsurfaces;i = j)
9993 // texture is the base texture pointer, rsurface.texture is the
9994 // current frame/skin the texture is directing us to use (for example
9995 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9996 // use skin 1 instead)
9997 texture = surfacelist[i]->texture;
9998 rsurface.texture = R_GetCurrentTexture(texture);
9999 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10001 // if this texture is not the kind we want, skip ahead to the next one
10002 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10006 if(FAKELIGHT_ENABLED || depthonly || prepass)
10008 rsurface.lightmaptexture = NULL;
10009 rsurface.deluxemaptexture = NULL;
10010 rsurface.uselightmaptexture = false;
10011 // simply scan ahead until we find a different texture or lightmap state
10012 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10017 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10018 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10019 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10020 // simply scan ahead until we find a different texture or lightmap state
10021 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10024 // render the range of surfaces
10025 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10027 R_FrameData_ReturnToMark();
10030 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10034 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10037 if (!rsurface.texture->currentnumlayers)
10039 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10040 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10042 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10044 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10045 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10046 else if (!rsurface.texture->currentnumlayers)
10048 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10050 // in the deferred case, transparent surfaces were queued during prepass
10051 if (!r_shadow_usingdeferredprepass)
10052 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10056 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10057 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10062 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10065 texture_t *texture;
10066 R_FrameData_SetMark();
10067 // break the surface list down into batches by texture and use of lightmapping
10068 for (i = 0;i < numsurfaces;i = j)
10071 // texture is the base texture pointer, rsurface.texture is the
10072 // current frame/skin the texture is directing us to use (for example
10073 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10074 // use skin 1 instead)
10075 texture = surfacelist[i]->texture;
10076 rsurface.texture = R_GetCurrentTexture(texture);
10077 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10079 // if this texture is not the kind we want, skip ahead to the next one
10080 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10084 if(FAKELIGHT_ENABLED || depthonly || prepass)
10086 rsurface.lightmaptexture = NULL;
10087 rsurface.deluxemaptexture = NULL;
10088 rsurface.uselightmaptexture = false;
10089 // simply scan ahead until we find a different texture or lightmap state
10090 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10095 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10096 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10097 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10098 // simply scan ahead until we find a different texture or lightmap state
10099 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10102 // render the range of surfaces
10103 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10105 R_FrameData_ReturnToMark();
10108 float locboxvertex3f[6*4*3] =
10110 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10111 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10112 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10113 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10114 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10115 1,0,0, 0,0,0, 0,1,0, 1,1,0
10118 unsigned short locboxelements[6*2*3] =
10123 12,13,14, 12,14,15,
10124 16,17,18, 16,18,19,
10128 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10131 cl_locnode_t *loc = (cl_locnode_t *)ent;
10133 float vertex3f[6*4*3];
10135 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10136 GL_DepthMask(false);
10137 GL_DepthRange(0, 1);
10138 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10139 GL_DepthTest(true);
10140 GL_CullFace(GL_NONE);
10141 R_EntityMatrix(&identitymatrix);
10143 // R_Mesh_ResetTextureState();
10145 i = surfacelist[0];
10146 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10147 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10148 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10149 surfacelist[0] < 0 ? 0.5f : 0.125f);
10151 if (VectorCompare(loc->mins, loc->maxs))
10153 VectorSet(size, 2, 2, 2);
10154 VectorMA(loc->mins, -0.5f, size, mins);
10158 VectorCopy(loc->mins, mins);
10159 VectorSubtract(loc->maxs, loc->mins, size);
10162 for (i = 0;i < 6*4*3;)
10163 for (j = 0;j < 3;j++, i++)
10164 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10166 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10167 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10168 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10171 void R_DrawLocs(void)
10174 cl_locnode_t *loc, *nearestloc;
10176 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10177 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10179 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10180 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10184 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10186 if (decalsystem->decals)
10187 Mem_Free(decalsystem->decals);
10188 memset(decalsystem, 0, sizeof(*decalsystem));
10191 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)
10194 tridecal_t *decals;
10197 // expand or initialize the system
10198 if (decalsystem->maxdecals <= decalsystem->numdecals)
10200 decalsystem_t old = *decalsystem;
10201 qboolean useshortelements;
10202 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10203 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10204 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)));
10205 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10206 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10207 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10208 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10209 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10210 if (decalsystem->numdecals)
10211 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10213 Mem_Free(old.decals);
10214 for (i = 0;i < decalsystem->maxdecals*3;i++)
10215 decalsystem->element3i[i] = i;
10216 if (useshortelements)
10217 for (i = 0;i < decalsystem->maxdecals*3;i++)
10218 decalsystem->element3s[i] = i;
10221 // grab a decal and search for another free slot for the next one
10222 decals = decalsystem->decals;
10223 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10224 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10226 decalsystem->freedecal = i;
10227 if (decalsystem->numdecals <= i)
10228 decalsystem->numdecals = i + 1;
10230 // initialize the decal
10232 decal->triangleindex = triangleindex;
10233 decal->surfaceindex = surfaceindex;
10234 decal->decalsequence = decalsequence;
10235 decal->color4f[0][0] = c0[0];
10236 decal->color4f[0][1] = c0[1];
10237 decal->color4f[0][2] = c0[2];
10238 decal->color4f[0][3] = 1;
10239 decal->color4f[1][0] = c1[0];
10240 decal->color4f[1][1] = c1[1];
10241 decal->color4f[1][2] = c1[2];
10242 decal->color4f[1][3] = 1;
10243 decal->color4f[2][0] = c2[0];
10244 decal->color4f[2][1] = c2[1];
10245 decal->color4f[2][2] = c2[2];
10246 decal->color4f[2][3] = 1;
10247 decal->vertex3f[0][0] = v0[0];
10248 decal->vertex3f[0][1] = v0[1];
10249 decal->vertex3f[0][2] = v0[2];
10250 decal->vertex3f[1][0] = v1[0];
10251 decal->vertex3f[1][1] = v1[1];
10252 decal->vertex3f[1][2] = v1[2];
10253 decal->vertex3f[2][0] = v2[0];
10254 decal->vertex3f[2][1] = v2[1];
10255 decal->vertex3f[2][2] = v2[2];
10256 decal->texcoord2f[0][0] = t0[0];
10257 decal->texcoord2f[0][1] = t0[1];
10258 decal->texcoord2f[1][0] = t1[0];
10259 decal->texcoord2f[1][1] = t1[1];
10260 decal->texcoord2f[2][0] = t2[0];
10261 decal->texcoord2f[2][1] = t2[1];
10264 extern cvar_t cl_decals_bias;
10265 extern cvar_t cl_decals_models;
10266 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10267 // baseparms, parms, temps
10268 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)
10273 const float *vertex3f;
10274 const float *normal3f;
10276 float points[2][9][3];
10283 e = rsurface.modelelement3i + 3*triangleindex;
10285 vertex3f = rsurface.modelvertex3f;
10286 normal3f = rsurface.modelnormal3f;
10290 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10292 index = 3*e[cornerindex];
10293 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10298 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10300 index = 3*e[cornerindex];
10301 VectorCopy(vertex3f + index, v[cornerindex]);
10306 //TriangleNormal(v[0], v[1], v[2], normal);
10307 //if (DotProduct(normal, localnormal) < 0.0f)
10309 // clip by each of the box planes formed from the projection matrix
10310 // if anything survives, we emit the decal
10311 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]);
10314 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]);
10317 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]);
10320 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]);
10323 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]);
10326 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]);
10329 // some part of the triangle survived, so we have to accept it...
10332 // dynamic always uses the original triangle
10334 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10336 index = 3*e[cornerindex];
10337 VectorCopy(vertex3f + index, v[cornerindex]);
10340 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10342 // convert vertex positions to texcoords
10343 Matrix4x4_Transform(projection, v[cornerindex], temp);
10344 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10345 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10346 // calculate distance fade from the projection origin
10347 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10348 f = bound(0.0f, f, 1.0f);
10349 c[cornerindex][0] = r * f;
10350 c[cornerindex][1] = g * f;
10351 c[cornerindex][2] = b * f;
10352 c[cornerindex][3] = 1.0f;
10353 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10356 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);
10358 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10359 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);
10361 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)
10363 matrix4x4_t projection;
10364 decalsystem_t *decalsystem;
10367 const msurface_t *surface;
10368 const msurface_t *surfaces;
10369 const int *surfacelist;
10370 const texture_t *texture;
10372 int numsurfacelist;
10373 int surfacelistindex;
10376 float localorigin[3];
10377 float localnormal[3];
10378 float localmins[3];
10379 float localmaxs[3];
10382 float planes[6][4];
10385 int bih_triangles_count;
10386 int bih_triangles[256];
10387 int bih_surfaces[256];
10389 decalsystem = &ent->decalsystem;
10390 model = ent->model;
10391 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10393 R_DecalSystem_Reset(&ent->decalsystem);
10397 if (!model->brush.data_leafs && !cl_decals_models.integer)
10399 if (decalsystem->model)
10400 R_DecalSystem_Reset(decalsystem);
10404 if (decalsystem->model != model)
10405 R_DecalSystem_Reset(decalsystem);
10406 decalsystem->model = model;
10408 RSurf_ActiveModelEntity(ent, true, false, false);
10410 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10411 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10412 VectorNormalize(localnormal);
10413 localsize = worldsize*rsurface.inversematrixscale;
10414 localmins[0] = localorigin[0] - localsize;
10415 localmins[1] = localorigin[1] - localsize;
10416 localmins[2] = localorigin[2] - localsize;
10417 localmaxs[0] = localorigin[0] + localsize;
10418 localmaxs[1] = localorigin[1] + localsize;
10419 localmaxs[2] = localorigin[2] + localsize;
10421 //VectorCopy(localnormal, planes[4]);
10422 //VectorVectors(planes[4], planes[2], planes[0]);
10423 AnglesFromVectors(angles, localnormal, NULL, false);
10424 AngleVectors(angles, planes[0], planes[2], planes[4]);
10425 VectorNegate(planes[0], planes[1]);
10426 VectorNegate(planes[2], planes[3]);
10427 VectorNegate(planes[4], planes[5]);
10428 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10429 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10430 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10431 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10432 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10433 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10438 matrix4x4_t forwardprojection;
10439 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10440 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10445 float projectionvector[4][3];
10446 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10447 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10448 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10449 projectionvector[0][0] = planes[0][0] * ilocalsize;
10450 projectionvector[0][1] = planes[1][0] * ilocalsize;
10451 projectionvector[0][2] = planes[2][0] * ilocalsize;
10452 projectionvector[1][0] = planes[0][1] * ilocalsize;
10453 projectionvector[1][1] = planes[1][1] * ilocalsize;
10454 projectionvector[1][2] = planes[2][1] * ilocalsize;
10455 projectionvector[2][0] = planes[0][2] * ilocalsize;
10456 projectionvector[2][1] = planes[1][2] * ilocalsize;
10457 projectionvector[2][2] = planes[2][2] * ilocalsize;
10458 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10459 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10460 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10461 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10465 dynamic = model->surfmesh.isanimated;
10466 numsurfacelist = model->nummodelsurfaces;
10467 surfacelist = model->sortedmodelsurfaces;
10468 surfaces = model->data_surfaces;
10471 bih_triangles_count = -1;
10474 if(model->render_bih.numleafs)
10475 bih = &model->render_bih;
10476 else if(model->collision_bih.numleafs)
10477 bih = &model->collision_bih;
10480 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10481 if(bih_triangles_count == 0)
10483 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10485 if(bih_triangles_count > 0)
10487 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10489 surfaceindex = bih_surfaces[triangleindex];
10490 surface = surfaces + surfaceindex;
10491 texture = surface->texture;
10492 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10494 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10496 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10501 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10503 surfaceindex = surfacelist[surfacelistindex];
10504 surface = surfaces + surfaceindex;
10505 // check cull box first because it rejects more than any other check
10506 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10508 // skip transparent surfaces
10509 texture = surface->texture;
10510 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10512 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10514 numtriangles = surface->num_triangles;
10515 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10516 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10521 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10522 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)
10524 int renderentityindex;
10525 float worldmins[3];
10526 float worldmaxs[3];
10527 entity_render_t *ent;
10529 if (!cl_decals_newsystem.integer)
10532 worldmins[0] = worldorigin[0] - worldsize;
10533 worldmins[1] = worldorigin[1] - worldsize;
10534 worldmins[2] = worldorigin[2] - worldsize;
10535 worldmaxs[0] = worldorigin[0] + worldsize;
10536 worldmaxs[1] = worldorigin[1] + worldsize;
10537 worldmaxs[2] = worldorigin[2] + worldsize;
10539 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10541 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10543 ent = r_refdef.scene.entities[renderentityindex];
10544 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10547 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10551 typedef struct r_decalsystem_splatqueue_s
10553 vec3_t worldorigin;
10554 vec3_t worldnormal;
10560 r_decalsystem_splatqueue_t;
10562 int r_decalsystem_numqueued = 0;
10563 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10565 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)
10567 r_decalsystem_splatqueue_t *queue;
10569 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10572 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10573 VectorCopy(worldorigin, queue->worldorigin);
10574 VectorCopy(worldnormal, queue->worldnormal);
10575 Vector4Set(queue->color, r, g, b, a);
10576 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10577 queue->worldsize = worldsize;
10578 queue->decalsequence = cl.decalsequence++;
10581 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10584 r_decalsystem_splatqueue_t *queue;
10586 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10587 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);
10588 r_decalsystem_numqueued = 0;
10591 extern cvar_t cl_decals_max;
10592 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10595 decalsystem_t *decalsystem = &ent->decalsystem;
10602 if (!decalsystem->numdecals)
10605 if (r_showsurfaces.integer)
10608 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10610 R_DecalSystem_Reset(decalsystem);
10614 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10615 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10617 if (decalsystem->lastupdatetime)
10618 frametime = (cl.time - decalsystem->lastupdatetime);
10621 decalsystem->lastupdatetime = cl.time;
10622 decal = decalsystem->decals;
10623 numdecals = decalsystem->numdecals;
10625 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10627 if (decal->color4f[0][3])
10629 decal->lived += frametime;
10630 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10632 memset(decal, 0, sizeof(*decal));
10633 if (decalsystem->freedecal > i)
10634 decalsystem->freedecal = i;
10638 decal = decalsystem->decals;
10639 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10642 // collapse the array by shuffling the tail decals into the gaps
10645 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10646 decalsystem->freedecal++;
10647 if (decalsystem->freedecal == numdecals)
10649 decal[decalsystem->freedecal] = decal[--numdecals];
10652 decalsystem->numdecals = numdecals;
10654 if (numdecals <= 0)
10656 // if there are no decals left, reset decalsystem
10657 R_DecalSystem_Reset(decalsystem);
10661 extern skinframe_t *decalskinframe;
10662 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10665 decalsystem_t *decalsystem = &ent->decalsystem;
10674 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10677 numdecals = decalsystem->numdecals;
10681 if (r_showsurfaces.integer)
10684 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10686 R_DecalSystem_Reset(decalsystem);
10690 // if the model is static it doesn't matter what value we give for
10691 // wantnormals and wanttangents, so this logic uses only rules applicable
10692 // to a model, knowing that they are meaningless otherwise
10693 if (ent == r_refdef.scene.worldentity)
10694 RSurf_ActiveWorldEntity();
10696 RSurf_ActiveModelEntity(ent, false, false, false);
10698 decalsystem->lastupdatetime = cl.time;
10699 decal = decalsystem->decals;
10701 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10703 // update vertex positions for animated models
10704 v3f = decalsystem->vertex3f;
10705 c4f = decalsystem->color4f;
10706 t2f = decalsystem->texcoord2f;
10707 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10709 if (!decal->color4f[0][3])
10712 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10715 // update color values for fading decals
10716 if (decal->lived >= cl_decals_time.value)
10717 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10721 c4f[ 0] = decal->color4f[0][0] * alpha;
10722 c4f[ 1] = decal->color4f[0][1] * alpha;
10723 c4f[ 2] = decal->color4f[0][2] * alpha;
10725 c4f[ 4] = decal->color4f[1][0] * alpha;
10726 c4f[ 5] = decal->color4f[1][1] * alpha;
10727 c4f[ 6] = decal->color4f[1][2] * alpha;
10729 c4f[ 8] = decal->color4f[2][0] * alpha;
10730 c4f[ 9] = decal->color4f[2][1] * alpha;
10731 c4f[10] = decal->color4f[2][2] * alpha;
10734 t2f[0] = decal->texcoord2f[0][0];
10735 t2f[1] = decal->texcoord2f[0][1];
10736 t2f[2] = decal->texcoord2f[1][0];
10737 t2f[3] = decal->texcoord2f[1][1];
10738 t2f[4] = decal->texcoord2f[2][0];
10739 t2f[5] = decal->texcoord2f[2][1];
10741 // update vertex positions for animated models
10742 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10744 e = rsurface.modelelement3i + 3*decal->triangleindex;
10745 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10746 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10747 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10751 VectorCopy(decal->vertex3f[0], v3f);
10752 VectorCopy(decal->vertex3f[1], v3f + 3);
10753 VectorCopy(decal->vertex3f[2], v3f + 6);
10756 if (r_refdef.fogenabled)
10758 alpha = RSurf_FogVertex(v3f);
10759 VectorScale(c4f, alpha, c4f);
10760 alpha = RSurf_FogVertex(v3f + 3);
10761 VectorScale(c4f + 4, alpha, c4f + 4);
10762 alpha = RSurf_FogVertex(v3f + 6);
10763 VectorScale(c4f + 8, alpha, c4f + 8);
10774 r_refdef.stats.drawndecals += numtris;
10776 // now render the decals all at once
10777 // (this assumes they all use one particle font texture!)
10778 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);
10779 // R_Mesh_ResetTextureState();
10780 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10781 GL_DepthMask(false);
10782 GL_DepthRange(0, 1);
10783 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10784 GL_DepthTest(true);
10785 GL_CullFace(GL_NONE);
10786 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10787 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10788 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10792 static void R_DrawModelDecals(void)
10796 // fade faster when there are too many decals
10797 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10798 for (i = 0;i < r_refdef.scene.numentities;i++)
10799 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10801 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10802 for (i = 0;i < r_refdef.scene.numentities;i++)
10803 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10804 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10806 R_DecalSystem_ApplySplatEntitiesQueue();
10808 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10809 for (i = 0;i < r_refdef.scene.numentities;i++)
10810 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10812 r_refdef.stats.totaldecals += numdecals;
10814 if (r_showsurfaces.integer)
10817 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10819 for (i = 0;i < r_refdef.scene.numentities;i++)
10821 if (!r_refdef.viewcache.entityvisible[i])
10823 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10824 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10828 extern cvar_t mod_collision_bih;
10829 void R_DrawDebugModel(void)
10831 entity_render_t *ent = rsurface.entity;
10832 int i, j, k, l, flagsmask;
10833 const msurface_t *surface;
10834 dp_model_t *model = ent->model;
10837 switch(vid.renderpath)
10839 case RENDERPATH_GL11:
10840 case RENDERPATH_GL13:
10841 case RENDERPATH_GL20:
10843 case RENDERPATH_D3D9:
10844 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10846 case RENDERPATH_D3D10:
10847 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10849 case RENDERPATH_D3D11:
10850 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10852 case RENDERPATH_SOFT:
10853 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10855 case RENDERPATH_GLES2:
10856 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10860 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10862 // R_Mesh_ResetTextureState();
10863 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10864 GL_DepthRange(0, 1);
10865 GL_DepthTest(!r_showdisabledepthtest.integer);
10866 GL_DepthMask(false);
10867 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10869 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10873 qboolean cullbox = ent == r_refdef.scene.worldentity;
10874 const q3mbrush_t *brush;
10875 const bih_t *bih = &model->collision_bih;
10876 const bih_leaf_t *bihleaf;
10877 float vertex3f[3][3];
10878 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10880 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10882 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10884 switch (bihleaf->type)
10887 brush = model->brush.data_brushes + bihleaf->itemindex;
10888 if (brush->colbrushf && brush->colbrushf->numtriangles)
10890 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);
10891 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10892 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10895 case BIH_COLLISIONTRIANGLE:
10896 triangleindex = bihleaf->itemindex;
10897 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10898 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10899 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10900 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);
10901 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10902 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10904 case BIH_RENDERTRIANGLE:
10905 triangleindex = bihleaf->itemindex;
10906 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10907 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10908 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10909 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);
10910 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10911 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10917 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10919 if (r_showtris.integer || (r_shownormals.value != 0))
10921 if (r_showdisabledepthtest.integer)
10923 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10924 GL_DepthMask(false);
10928 GL_BlendFunc(GL_ONE, GL_ZERO);
10929 GL_DepthMask(true);
10931 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10933 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10935 rsurface.texture = R_GetCurrentTexture(surface->texture);
10936 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10938 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10939 if (r_showtris.value > 0)
10941 if (!rsurface.texture->currentlayers->depthmask)
10942 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10943 else if (ent == r_refdef.scene.worldentity)
10944 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10946 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10947 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10948 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10950 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10953 if (r_shownormals.value < 0)
10955 qglBegin(GL_LINES);
10956 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10958 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10959 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10960 qglVertex3f(v[0], v[1], v[2]);
10961 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10962 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10963 qglVertex3f(v[0], v[1], v[2]);
10968 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10970 qglBegin(GL_LINES);
10971 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10973 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10974 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10975 qglVertex3f(v[0], v[1], v[2]);
10976 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10977 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10978 qglVertex3f(v[0], v[1], v[2]);
10982 qglBegin(GL_LINES);
10983 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10985 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10986 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10987 qglVertex3f(v[0], v[1], v[2]);
10988 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10989 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10990 qglVertex3f(v[0], v[1], v[2]);
10994 qglBegin(GL_LINES);
10995 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10997 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10998 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10999 qglVertex3f(v[0], v[1], v[2]);
11000 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11001 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11002 qglVertex3f(v[0], v[1], v[2]);
11009 rsurface.texture = NULL;
11013 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11014 int r_maxsurfacelist = 0;
11015 const msurface_t **r_surfacelist = NULL;
11016 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11018 int i, j, endj, flagsmask;
11019 dp_model_t *model = r_refdef.scene.worldmodel;
11020 msurface_t *surfaces;
11021 unsigned char *update;
11022 int numsurfacelist = 0;
11026 if (r_maxsurfacelist < model->num_surfaces)
11028 r_maxsurfacelist = model->num_surfaces;
11030 Mem_Free((msurface_t**)r_surfacelist);
11031 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11034 RSurf_ActiveWorldEntity();
11036 surfaces = model->data_surfaces;
11037 update = model->brushq1.lightmapupdateflags;
11039 // update light styles on this submodel
11040 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11042 model_brush_lightstyleinfo_t *style;
11043 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11045 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11047 int *list = style->surfacelist;
11048 style->value = r_refdef.scene.lightstylevalue[style->style];
11049 for (j = 0;j < style->numsurfaces;j++)
11050 update[list[j]] = true;
11055 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11059 R_DrawDebugModel();
11060 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11064 rsurface.lightmaptexture = NULL;
11065 rsurface.deluxemaptexture = NULL;
11066 rsurface.uselightmaptexture = false;
11067 rsurface.texture = NULL;
11068 rsurface.rtlight = NULL;
11069 numsurfacelist = 0;
11070 // add visible surfaces to draw list
11071 for (i = 0;i < model->nummodelsurfaces;i++)
11073 j = model->sortedmodelsurfaces[i];
11074 if (r_refdef.viewcache.world_surfacevisible[j])
11075 r_surfacelist[numsurfacelist++] = surfaces + j;
11077 // update lightmaps if needed
11078 if (model->brushq1.firstrender)
11080 model->brushq1.firstrender = false;
11081 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11083 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11087 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11088 if (r_refdef.viewcache.world_surfacevisible[j])
11090 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11092 // don't do anything if there were no surfaces
11093 if (!numsurfacelist)
11095 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11098 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11100 // add to stats if desired
11101 if (r_speeds.integer && !skysurfaces && !depthonly)
11103 r_refdef.stats.world_surfaces += numsurfacelist;
11104 for (j = 0;j < numsurfacelist;j++)
11105 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11108 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11111 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11113 int i, j, endj, flagsmask;
11114 dp_model_t *model = ent->model;
11115 msurface_t *surfaces;
11116 unsigned char *update;
11117 int numsurfacelist = 0;
11121 if (r_maxsurfacelist < model->num_surfaces)
11123 r_maxsurfacelist = model->num_surfaces;
11125 Mem_Free((msurface_t **)r_surfacelist);
11126 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11129 // if the model is static it doesn't matter what value we give for
11130 // wantnormals and wanttangents, so this logic uses only rules applicable
11131 // to a model, knowing that they are meaningless otherwise
11132 if (ent == r_refdef.scene.worldentity)
11133 RSurf_ActiveWorldEntity();
11134 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11135 RSurf_ActiveModelEntity(ent, false, false, false);
11137 RSurf_ActiveModelEntity(ent, true, true, true);
11138 else if (depthonly)
11140 switch (vid.renderpath)
11142 case RENDERPATH_GL20:
11143 case RENDERPATH_D3D9:
11144 case RENDERPATH_D3D10:
11145 case RENDERPATH_D3D11:
11146 case RENDERPATH_SOFT:
11147 case RENDERPATH_GLES2:
11148 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11150 case RENDERPATH_GL13:
11151 case RENDERPATH_GL11:
11152 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11158 switch (vid.renderpath)
11160 case RENDERPATH_GL20:
11161 case RENDERPATH_D3D9:
11162 case RENDERPATH_D3D10:
11163 case RENDERPATH_D3D11:
11164 case RENDERPATH_SOFT:
11165 case RENDERPATH_GLES2:
11166 RSurf_ActiveModelEntity(ent, true, true, false);
11168 case RENDERPATH_GL13:
11169 case RENDERPATH_GL11:
11170 RSurf_ActiveModelEntity(ent, true, false, false);
11175 surfaces = model->data_surfaces;
11176 update = model->brushq1.lightmapupdateflags;
11178 // update light styles
11179 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11181 model_brush_lightstyleinfo_t *style;
11182 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11184 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11186 int *list = style->surfacelist;
11187 style->value = r_refdef.scene.lightstylevalue[style->style];
11188 for (j = 0;j < style->numsurfaces;j++)
11189 update[list[j]] = true;
11194 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11198 R_DrawDebugModel();
11199 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11203 rsurface.lightmaptexture = NULL;
11204 rsurface.deluxemaptexture = NULL;
11205 rsurface.uselightmaptexture = false;
11206 rsurface.texture = NULL;
11207 rsurface.rtlight = NULL;
11208 numsurfacelist = 0;
11209 // add visible surfaces to draw list
11210 for (i = 0;i < model->nummodelsurfaces;i++)
11211 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11212 // don't do anything if there were no surfaces
11213 if (!numsurfacelist)
11215 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11218 // update lightmaps if needed
11222 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11227 R_BuildLightMap(ent, surfaces + j);
11232 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11234 R_BuildLightMap(ent, surfaces + j);
11235 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11237 // add to stats if desired
11238 if (r_speeds.integer && !skysurfaces && !depthonly)
11240 r_refdef.stats.entities_surfaces += numsurfacelist;
11241 for (j = 0;j < numsurfacelist;j++)
11242 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11245 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11248 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11250 static texture_t texture;
11251 static msurface_t surface;
11252 const msurface_t *surfacelist = &surface;
11254 // fake enough texture and surface state to render this geometry
11256 texture.update_lastrenderframe = -1; // regenerate this texture
11257 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11258 texture.currentskinframe = skinframe;
11259 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11260 texture.offsetmapping = OFFSETMAPPING_OFF;
11261 texture.offsetscale = 1;
11262 texture.specularscalemod = 1;
11263 texture.specularpowermod = 1;
11265 surface.texture = &texture;
11266 surface.num_triangles = numtriangles;
11267 surface.num_firsttriangle = firsttriangle;
11268 surface.num_vertices = numvertices;
11269 surface.num_firstvertex = firstvertex;
11272 rsurface.texture = R_GetCurrentTexture(surface.texture);
11273 rsurface.lightmaptexture = NULL;
11274 rsurface.deluxemaptexture = NULL;
11275 rsurface.uselightmaptexture = false;
11276 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11279 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)
11281 static msurface_t surface;
11282 const msurface_t *surfacelist = &surface;
11284 // fake enough texture and surface state to render this geometry
11285 surface.texture = texture;
11286 surface.num_triangles = numtriangles;
11287 surface.num_firsttriangle = firsttriangle;
11288 surface.num_vertices = numvertices;
11289 surface.num_firstvertex = firstvertex;
11292 rsurface.texture = R_GetCurrentTexture(surface.texture);
11293 rsurface.lightmaptexture = NULL;
11294 rsurface.deluxemaptexture = NULL;
11295 rsurface.uselightmaptexture = false;
11296 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);