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";
992 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
993 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
994 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
997 // the first pretext is which type of shader to compile as
998 // (later these will all be bound together as a program object)
999 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1000 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1001 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1003 // the second pretext is the mode (for example a light source)
1004 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1005 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1006 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1007 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1009 // now add all the permutation pretexts
1010 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1012 if (permutation & (1<<i))
1014 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1015 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1016 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1017 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1021 // keep line numbers correct
1022 vertstrings_list[vertstrings_count++] = "\n";
1023 geomstrings_list[geomstrings_count++] = "\n";
1024 fragstrings_list[fragstrings_count++] = "\n";
1029 R_CompileShader_AddStaticParms(mode, permutation);
1030 memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1031 vertstrings_count += shaderstaticparms_count;
1032 memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1033 geomstrings_count += shaderstaticparms_count;
1034 memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1035 fragstrings_count += shaderstaticparms_count;
1037 // now append the shader text itself
1038 vertstrings_list[vertstrings_count++] = vertexstring;
1039 geomstrings_list[geomstrings_count++] = geometrystring;
1040 fragstrings_list[fragstrings_count++] = fragmentstring;
1042 // if any sources were NULL, clear the respective list
1044 vertstrings_count = 0;
1045 if (!geometrystring)
1046 geomstrings_count = 0;
1047 if (!fragmentstring)
1048 fragstrings_count = 0;
1050 // compile the shader program
1051 if (vertstrings_count + geomstrings_count + fragstrings_count)
1052 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1056 qglUseProgram(p->program);CHECKGLERROR
1057 // look up all the uniform variable names we care about, so we don't
1058 // have to look them up every time we set them
1060 p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First");
1061 p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second");
1062 p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1063 p->loc_Texture_Normal = qglGetUniformLocation(p->program, "Texture_Normal");
1064 p->loc_Texture_Color = qglGetUniformLocation(p->program, "Texture_Color");
1065 p->loc_Texture_Gloss = qglGetUniformLocation(p->program, "Texture_Gloss");
1066 p->loc_Texture_Glow = qglGetUniformLocation(p->program, "Texture_Glow");
1067 p->loc_Texture_SecondaryNormal = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1068 p->loc_Texture_SecondaryColor = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1069 p->loc_Texture_SecondaryGloss = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1070 p->loc_Texture_SecondaryGlow = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1071 p->loc_Texture_Pants = qglGetUniformLocation(p->program, "Texture_Pants");
1072 p->loc_Texture_Shirt = qglGetUniformLocation(p->program, "Texture_Shirt");
1073 p->loc_Texture_FogHeightTexture = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1074 p->loc_Texture_FogMask = qglGetUniformLocation(p->program, "Texture_FogMask");
1075 p->loc_Texture_Lightmap = qglGetUniformLocation(p->program, "Texture_Lightmap");
1076 p->loc_Texture_Deluxemap = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1077 p->loc_Texture_Attenuation = qglGetUniformLocation(p->program, "Texture_Attenuation");
1078 p->loc_Texture_Cube = qglGetUniformLocation(p->program, "Texture_Cube");
1079 p->loc_Texture_Refraction = qglGetUniformLocation(p->program, "Texture_Refraction");
1080 p->loc_Texture_Reflection = qglGetUniformLocation(p->program, "Texture_Reflection");
1081 p->loc_Texture_ShadowMap2D = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1082 p->loc_Texture_CubeProjection = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1083 p->loc_Texture_ScreenDepth = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1084 p->loc_Texture_ScreenNormalMap = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1085 p->loc_Texture_ScreenDiffuse = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1086 p->loc_Texture_ScreenSpecular = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1087 p->loc_Texture_ReflectMask = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1088 p->loc_Texture_ReflectCube = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1089 p->loc_Texture_BounceGrid = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1090 p->loc_Alpha = qglGetUniformLocation(p->program, "Alpha");
1091 p->loc_BloomBlur_Parameters = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1092 p->loc_ClientTime = qglGetUniformLocation(p->program, "ClientTime");
1093 p->loc_Color_Ambient = qglGetUniformLocation(p->program, "Color_Ambient");
1094 p->loc_Color_Diffuse = qglGetUniformLocation(p->program, "Color_Diffuse");
1095 p->loc_Color_Specular = qglGetUniformLocation(p->program, "Color_Specular");
1096 p->loc_Color_Glow = qglGetUniformLocation(p->program, "Color_Glow");
1097 p->loc_Color_Pants = qglGetUniformLocation(p->program, "Color_Pants");
1098 p->loc_Color_Shirt = qglGetUniformLocation(p->program, "Color_Shirt");
1099 p->loc_DeferredColor_Ambient = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1100 p->loc_DeferredColor_Diffuse = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1101 p->loc_DeferredColor_Specular = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1102 p->loc_DeferredMod_Diffuse = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1103 p->loc_DeferredMod_Specular = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1104 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1105 p->loc_EyePosition = qglGetUniformLocation(p->program, "EyePosition");
1106 p->loc_FogColor = qglGetUniformLocation(p->program, "FogColor");
1107 p->loc_FogHeightFade = qglGetUniformLocation(p->program, "FogHeightFade");
1108 p->loc_FogPlane = qglGetUniformLocation(p->program, "FogPlane");
1109 p->loc_FogPlaneViewDist = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1110 p->loc_FogRangeRecip = qglGetUniformLocation(p->program, "FogRangeRecip");
1111 p->loc_LightColor = qglGetUniformLocation(p->program, "LightColor");
1112 p->loc_LightDir = qglGetUniformLocation(p->program, "LightDir");
1113 p->loc_LightPosition = qglGetUniformLocation(p->program, "LightPosition");
1114 p->loc_OffsetMapping_ScaleSteps = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1115 p->loc_PixelSize = qglGetUniformLocation(p->program, "PixelSize");
1116 p->loc_ReflectColor = qglGetUniformLocation(p->program, "ReflectColor");
1117 p->loc_ReflectFactor = qglGetUniformLocation(p->program, "ReflectFactor");
1118 p->loc_ReflectOffset = qglGetUniformLocation(p->program, "ReflectOffset");
1119 p->loc_RefractColor = qglGetUniformLocation(p->program, "RefractColor");
1120 p->loc_Saturation = qglGetUniformLocation(p->program, "Saturation");
1121 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1122 p->loc_ScreenScaleRefractReflect = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1123 p->loc_ScreenToDepth = qglGetUniformLocation(p->program, "ScreenToDepth");
1124 p->loc_ShadowMap_Parameters = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1125 p->loc_ShadowMap_TextureScale = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1126 p->loc_SpecularPower = qglGetUniformLocation(p->program, "SpecularPower");
1127 p->loc_UserVec1 = qglGetUniformLocation(p->program, "UserVec1");
1128 p->loc_UserVec2 = qglGetUniformLocation(p->program, "UserVec2");
1129 p->loc_UserVec3 = qglGetUniformLocation(p->program, "UserVec3");
1130 p->loc_UserVec4 = qglGetUniformLocation(p->program, "UserVec4");
1131 p->loc_ViewTintColor = qglGetUniformLocation(p->program, "ViewTintColor");
1132 p->loc_ViewToLight = qglGetUniformLocation(p->program, "ViewToLight");
1133 p->loc_ModelToLight = qglGetUniformLocation(p->program, "ModelToLight");
1134 p->loc_TexMatrix = qglGetUniformLocation(p->program, "TexMatrix");
1135 p->loc_BackgroundTexMatrix = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1136 p->loc_ModelViewMatrix = qglGetUniformLocation(p->program, "ModelViewMatrix");
1137 p->loc_ModelViewProjectionMatrix = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1138 p->loc_PixelToScreenTexCoord = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1139 p->loc_ModelToReflectCube = qglGetUniformLocation(p->program, "ModelToReflectCube");
1140 p->loc_ShadowMapMatrix = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1141 p->loc_BloomColorSubtract = qglGetUniformLocation(p->program, "BloomColorSubtract");
1142 p->loc_NormalmapScrollBlend = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1143 p->loc_BounceGridMatrix = qglGetUniformLocation(p->program, "BounceGridMatrix");
1144 p->loc_BounceGridIntensity = qglGetUniformLocation(p->program, "BounceGridIntensity");
1145 // initialize the samplers to refer to the texture units we use
1146 p->tex_Texture_First = -1;
1147 p->tex_Texture_Second = -1;
1148 p->tex_Texture_GammaRamps = -1;
1149 p->tex_Texture_Normal = -1;
1150 p->tex_Texture_Color = -1;
1151 p->tex_Texture_Gloss = -1;
1152 p->tex_Texture_Glow = -1;
1153 p->tex_Texture_SecondaryNormal = -1;
1154 p->tex_Texture_SecondaryColor = -1;
1155 p->tex_Texture_SecondaryGloss = -1;
1156 p->tex_Texture_SecondaryGlow = -1;
1157 p->tex_Texture_Pants = -1;
1158 p->tex_Texture_Shirt = -1;
1159 p->tex_Texture_FogHeightTexture = -1;
1160 p->tex_Texture_FogMask = -1;
1161 p->tex_Texture_Lightmap = -1;
1162 p->tex_Texture_Deluxemap = -1;
1163 p->tex_Texture_Attenuation = -1;
1164 p->tex_Texture_Cube = -1;
1165 p->tex_Texture_Refraction = -1;
1166 p->tex_Texture_Reflection = -1;
1167 p->tex_Texture_ShadowMap2D = -1;
1168 p->tex_Texture_CubeProjection = -1;
1169 p->tex_Texture_ScreenDepth = -1;
1170 p->tex_Texture_ScreenNormalMap = -1;
1171 p->tex_Texture_ScreenDiffuse = -1;
1172 p->tex_Texture_ScreenSpecular = -1;
1173 p->tex_Texture_ReflectMask = -1;
1174 p->tex_Texture_ReflectCube = -1;
1175 p->tex_Texture_BounceGrid = -1;
1177 if (p->loc_Texture_First >= 0) {p->tex_Texture_First = sampler;qglUniform1i(p->loc_Texture_First , sampler);sampler++;}
1178 if (p->loc_Texture_Second >= 0) {p->tex_Texture_Second = sampler;qglUniform1i(p->loc_Texture_Second , sampler);sampler++;}
1179 if (p->loc_Texture_GammaRamps >= 0) {p->tex_Texture_GammaRamps = sampler;qglUniform1i(p->loc_Texture_GammaRamps , sampler);sampler++;}
1180 if (p->loc_Texture_Normal >= 0) {p->tex_Texture_Normal = sampler;qglUniform1i(p->loc_Texture_Normal , sampler);sampler++;}
1181 if (p->loc_Texture_Color >= 0) {p->tex_Texture_Color = sampler;qglUniform1i(p->loc_Texture_Color , sampler);sampler++;}
1182 if (p->loc_Texture_Gloss >= 0) {p->tex_Texture_Gloss = sampler;qglUniform1i(p->loc_Texture_Gloss , sampler);sampler++;}
1183 if (p->loc_Texture_Glow >= 0) {p->tex_Texture_Glow = sampler;qglUniform1i(p->loc_Texture_Glow , sampler);sampler++;}
1184 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1185 if (p->loc_Texture_SecondaryColor >= 0) {p->tex_Texture_SecondaryColor = sampler;qglUniform1i(p->loc_Texture_SecondaryColor , sampler);sampler++;}
1186 if (p->loc_Texture_SecondaryGloss >= 0) {p->tex_Texture_SecondaryGloss = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss , sampler);sampler++;}
1187 if (p->loc_Texture_SecondaryGlow >= 0) {p->tex_Texture_SecondaryGlow = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow , sampler);sampler++;}
1188 if (p->loc_Texture_Pants >= 0) {p->tex_Texture_Pants = sampler;qglUniform1i(p->loc_Texture_Pants , sampler);sampler++;}
1189 if (p->loc_Texture_Shirt >= 0) {p->tex_Texture_Shirt = sampler;qglUniform1i(p->loc_Texture_Shirt , sampler);sampler++;}
1190 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1191 if (p->loc_Texture_FogMask >= 0) {p->tex_Texture_FogMask = sampler;qglUniform1i(p->loc_Texture_FogMask , sampler);sampler++;}
1192 if (p->loc_Texture_Lightmap >= 0) {p->tex_Texture_Lightmap = sampler;qglUniform1i(p->loc_Texture_Lightmap , sampler);sampler++;}
1193 if (p->loc_Texture_Deluxemap >= 0) {p->tex_Texture_Deluxemap = sampler;qglUniform1i(p->loc_Texture_Deluxemap , sampler);sampler++;}
1194 if (p->loc_Texture_Attenuation >= 0) {p->tex_Texture_Attenuation = sampler;qglUniform1i(p->loc_Texture_Attenuation , sampler);sampler++;}
1195 if (p->loc_Texture_Cube >= 0) {p->tex_Texture_Cube = sampler;qglUniform1i(p->loc_Texture_Cube , sampler);sampler++;}
1196 if (p->loc_Texture_Refraction >= 0) {p->tex_Texture_Refraction = sampler;qglUniform1i(p->loc_Texture_Refraction , sampler);sampler++;}
1197 if (p->loc_Texture_Reflection >= 0) {p->tex_Texture_Reflection = sampler;qglUniform1i(p->loc_Texture_Reflection , sampler);sampler++;}
1198 if (p->loc_Texture_ShadowMap2D >= 0) {p->tex_Texture_ShadowMap2D = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D , sampler);sampler++;}
1199 if (p->loc_Texture_CubeProjection >= 0) {p->tex_Texture_CubeProjection = sampler;qglUniform1i(p->loc_Texture_CubeProjection , sampler);sampler++;}
1200 if (p->loc_Texture_ScreenDepth >= 0) {p->tex_Texture_ScreenDepth = sampler;qglUniform1i(p->loc_Texture_ScreenDepth , sampler);sampler++;}
1201 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1202 if (p->loc_Texture_ScreenDiffuse >= 0) {p->tex_Texture_ScreenDiffuse = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse , sampler);sampler++;}
1203 if (p->loc_Texture_ScreenSpecular >= 0) {p->tex_Texture_ScreenSpecular = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular , sampler);sampler++;}
1204 if (p->loc_Texture_ReflectMask >= 0) {p->tex_Texture_ReflectMask = sampler;qglUniform1i(p->loc_Texture_ReflectMask , sampler);sampler++;}
1205 if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;}
1206 if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;}
1208 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1211 Con_Printf("^1GLSL shader %s failed! some features may not work properly.\n", permutationname);
1215 Mem_Free(vertexstring);
1217 Mem_Free(geometrystring);
1219 Mem_Free(fragmentstring);
1222 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1224 r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1225 if (r_glsl_permutation != perm)
1227 r_glsl_permutation = perm;
1228 if (!r_glsl_permutation->program)
1230 if (!r_glsl_permutation->compiled)
1231 R_GLSL_CompilePermutation(perm, mode, permutation);
1232 if (!r_glsl_permutation->program)
1234 // remove features until we find a valid permutation
1236 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1238 // reduce i more quickly whenever it would not remove any bits
1239 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1240 if (!(permutation & j))
1243 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1244 if (!r_glsl_permutation->compiled)
1245 R_GLSL_CompilePermutation(perm, mode, permutation);
1246 if (r_glsl_permutation->program)
1249 if (i >= SHADERPERMUTATION_COUNT)
1251 //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1252 r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1253 qglUseProgram(0);CHECKGLERROR
1254 return; // no bit left to clear, entire mode is broken
1259 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1261 if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1262 if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1263 if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1270 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1271 extern D3DCAPS9 vid_d3d9caps;
1274 struct r_hlsl_permutation_s;
1275 typedef struct r_hlsl_permutation_s
1277 /// hash lookup data
1278 struct r_hlsl_permutation_s *hashnext;
1280 unsigned int permutation;
1282 /// indicates if we have tried compiling this permutation already
1284 /// NULL if compilation failed
1285 IDirect3DVertexShader9 *vertexshader;
1286 IDirect3DPixelShader9 *pixelshader;
1288 r_hlsl_permutation_t;
1290 typedef enum D3DVSREGISTER_e
1292 D3DVSREGISTER_TexMatrix = 0, // float4x4
1293 D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1294 D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1295 D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1296 D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1297 D3DVSREGISTER_ModelToLight = 20, // float4x4
1298 D3DVSREGISTER_EyePosition = 24,
1299 D3DVSREGISTER_FogPlane = 25,
1300 D3DVSREGISTER_LightDir = 26,
1301 D3DVSREGISTER_LightPosition = 27,
1305 typedef enum D3DPSREGISTER_e
1307 D3DPSREGISTER_Alpha = 0,
1308 D3DPSREGISTER_BloomBlur_Parameters = 1,
1309 D3DPSREGISTER_ClientTime = 2,
1310 D3DPSREGISTER_Color_Ambient = 3,
1311 D3DPSREGISTER_Color_Diffuse = 4,
1312 D3DPSREGISTER_Color_Specular = 5,
1313 D3DPSREGISTER_Color_Glow = 6,
1314 D3DPSREGISTER_Color_Pants = 7,
1315 D3DPSREGISTER_Color_Shirt = 8,
1316 D3DPSREGISTER_DeferredColor_Ambient = 9,
1317 D3DPSREGISTER_DeferredColor_Diffuse = 10,
1318 D3DPSREGISTER_DeferredColor_Specular = 11,
1319 D3DPSREGISTER_DeferredMod_Diffuse = 12,
1320 D3DPSREGISTER_DeferredMod_Specular = 13,
1321 D3DPSREGISTER_DistortScaleRefractReflect = 14,
1322 D3DPSREGISTER_EyePosition = 15, // unused
1323 D3DPSREGISTER_FogColor = 16,
1324 D3DPSREGISTER_FogHeightFade = 17,
1325 D3DPSREGISTER_FogPlane = 18,
1326 D3DPSREGISTER_FogPlaneViewDist = 19,
1327 D3DPSREGISTER_FogRangeRecip = 20,
1328 D3DPSREGISTER_LightColor = 21,
1329 D3DPSREGISTER_LightDir = 22, // unused
1330 D3DPSREGISTER_LightPosition = 23,
1331 D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1332 D3DPSREGISTER_PixelSize = 25,
1333 D3DPSREGISTER_ReflectColor = 26,
1334 D3DPSREGISTER_ReflectFactor = 27,
1335 D3DPSREGISTER_ReflectOffset = 28,
1336 D3DPSREGISTER_RefractColor = 29,
1337 D3DPSREGISTER_Saturation = 30,
1338 D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1339 D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1340 D3DPSREGISTER_ScreenToDepth = 33,
1341 D3DPSREGISTER_ShadowMap_Parameters = 34,
1342 D3DPSREGISTER_ShadowMap_TextureScale = 35,
1343 D3DPSREGISTER_SpecularPower = 36,
1344 D3DPSREGISTER_UserVec1 = 37,
1345 D3DPSREGISTER_UserVec2 = 38,
1346 D3DPSREGISTER_UserVec3 = 39,
1347 D3DPSREGISTER_UserVec4 = 40,
1348 D3DPSREGISTER_ViewTintColor = 41,
1349 D3DPSREGISTER_PixelToScreenTexCoord = 42,
1350 D3DPSREGISTER_BloomColorSubtract = 43,
1351 D3DPSREGISTER_ViewToLight = 44, // float4x4
1352 D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1353 D3DPSREGISTER_NormalmapScrollBlend = 52,
1358 /// information about each possible shader permutation
1359 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1360 /// currently selected permutation
1361 r_hlsl_permutation_t *r_hlsl_permutation;
1362 /// storage for permutations linked in the hash table
1363 memexpandablearray_t r_hlsl_permutationarray;
1365 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1367 //unsigned int hashdepth = 0;
1368 unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1369 r_hlsl_permutation_t *p;
1370 for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1372 if (p->mode == mode && p->permutation == permutation)
1374 //if (hashdepth > 10)
1375 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1380 p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1382 p->permutation = permutation;
1383 p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1384 r_hlsl_permutationhash[mode][hashindex] = p;
1385 //if (hashdepth > 10)
1386 // Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1390 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1393 if (!filename || !filename[0])
1395 if (!strcmp(filename, "hlsl/default.hlsl"))
1397 if (!hlslshaderstring)
1399 hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1400 if (hlslshaderstring)
1401 Con_DPrintf("Loading shaders from file %s...\n", filename);
1403 hlslshaderstring = (char *)builtinhlslshaderstring;
1405 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1406 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1407 return shaderstring;
1409 shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1412 if (printfromdisknotice)
1413 Con_DPrintf("from disk %s... ", filename);
1414 return shaderstring;
1416 return shaderstring;
1420 //#include <d3dx9shader.h>
1421 //#include <d3dx9mesh.h>
1423 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1425 DWORD *vsbin = NULL;
1426 DWORD *psbin = NULL;
1427 fs_offset_t vsbinsize;
1428 fs_offset_t psbinsize;
1429 // IDirect3DVertexShader9 *vs = NULL;
1430 // IDirect3DPixelShader9 *ps = NULL;
1431 ID3DXBuffer *vslog = NULL;
1432 ID3DXBuffer *vsbuffer = NULL;
1433 ID3DXConstantTable *vsconstanttable = NULL;
1434 ID3DXBuffer *pslog = NULL;
1435 ID3DXBuffer *psbuffer = NULL;
1436 ID3DXConstantTable *psconstanttable = NULL;
1439 char temp[MAX_INPUTLINE];
1440 const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1441 qboolean debugshader = gl_paranoid.integer != 0;
1442 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1443 if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1446 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1447 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1449 if ((!vsbin && vertstring) || (!psbin && fragstring))
1451 const char* dllnames_d3dx9 [] =
1475 dllhandle_t d3dx9_dll = NULL;
1476 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1477 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1478 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1479 dllfunction_t d3dx9_dllfuncs[] =
1481 {"D3DXCompileShaderFromFileA", (void **) &qD3DXCompileShaderFromFileA},
1482 {"D3DXPreprocessShader", (void **) &qD3DXPreprocessShader},
1483 {"D3DXCompileShader", (void **) &qD3DXCompileShader},
1486 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1488 DWORD shaderflags = 0;
1490 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1491 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1492 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1493 if (vertstring && vertstring[0])
1497 // vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1498 // FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1499 FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1500 vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1503 vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1506 vsbinsize = vsbuffer->GetBufferSize();
1507 vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1508 memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1509 vsbuffer->Release();
1513 strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1514 Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1518 if (fragstring && fragstring[0])
1522 // psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1523 // FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1524 FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1525 psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1528 psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1531 psbinsize = psbuffer->GetBufferSize();
1532 psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1533 memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1534 psbuffer->Release();
1538 strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1539 Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1543 Sys_UnloadLibrary(&d3dx9_dll);
1546 Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1550 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1551 if (FAILED(vsresult))
1552 Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1553 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1554 if (FAILED(psresult))
1555 Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1557 // free the shader data
1558 vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1559 psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1562 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1565 shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1566 int vertstring_length = 0;
1567 int geomstring_length = 0;
1568 int fragstring_length = 0;
1570 char *vertexstring, *geometrystring, *fragmentstring;
1571 char *vertstring, *geomstring, *fragstring;
1572 char permutationname[256];
1573 char cachename[256];
1574 int vertstrings_count = 0;
1575 int geomstrings_count = 0;
1576 int fragstrings_count = 0;
1577 const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1578 const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1579 const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1584 p->vertexshader = NULL;
1585 p->pixelshader = NULL;
1587 permutationname[0] = 0;
1589 vertexstring = R_HLSL_GetText(modeinfo->vertexfilename, true);
1590 geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1591 fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1593 strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1594 strlcat(cachename, "hlsl/", sizeof(cachename));
1596 // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1597 vertstrings_count = 0;
1598 geomstrings_count = 0;
1599 fragstrings_count = 0;
1600 vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1601 geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1602 fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1604 // the first pretext is which type of shader to compile as
1605 // (later these will all be bound together as a program object)
1606 vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1607 geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1608 fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1610 // the second pretext is the mode (for example a light source)
1611 vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1612 geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1613 fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1614 strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1615 strlcat(cachename, modeinfo->name, sizeof(cachename));
1617 // now add all the permutation pretexts
1618 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1620 if (permutation & (1<<i))
1622 vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1623 geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1624 fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1625 strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1626 strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1630 // keep line numbers correct
1631 vertstrings_list[vertstrings_count++] = "\n";
1632 geomstrings_list[geomstrings_count++] = "\n";
1633 fragstrings_list[fragstrings_count++] = "\n";
1638 R_CompileShader_AddStaticParms(mode, permutation);
1639 memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1640 vertstrings_count += shaderstaticparms_count;
1641 memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1642 geomstrings_count += shaderstaticparms_count;
1643 memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1644 fragstrings_count += shaderstaticparms_count;
1646 // replace spaces in the cachename with _ characters
1647 for (i = 0;cachename[i];i++)
1648 if (cachename[i] == ' ')
1651 // now append the shader text itself
1652 vertstrings_list[vertstrings_count++] = vertexstring;
1653 geomstrings_list[geomstrings_count++] = geometrystring;
1654 fragstrings_list[fragstrings_count++] = fragmentstring;
1656 // if any sources were NULL, clear the respective list
1658 vertstrings_count = 0;
1659 if (!geometrystring)
1660 geomstrings_count = 0;
1661 if (!fragmentstring)
1662 fragstrings_count = 0;
1664 vertstring_length = 0;
1665 for (i = 0;i < vertstrings_count;i++)
1666 vertstring_length += strlen(vertstrings_list[i]);
1667 vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1668 for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1669 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1671 geomstring_length = 0;
1672 for (i = 0;i < geomstrings_count;i++)
1673 geomstring_length += strlen(geomstrings_list[i]);
1674 geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1675 for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1676 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1678 fragstring_length = 0;
1679 for (i = 0;i < fragstrings_count;i++)
1680 fragstring_length += strlen(fragstrings_list[i]);
1681 fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1682 for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1683 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1685 // try to load the cached shader, or generate one
1686 R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1688 if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1689 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1691 Con_Printf("^1HLSL shader %s failed! some features may not work properly.\n", permutationname);
1695 Mem_Free(vertstring);
1697 Mem_Free(geomstring);
1699 Mem_Free(fragstring);
1701 Mem_Free(vertexstring);
1703 Mem_Free(geometrystring);
1705 Mem_Free(fragmentstring);
1708 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1709 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1710 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);}
1711 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);}
1712 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);}
1713 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);}
1715 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1716 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1717 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);}
1718 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);}
1719 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);}
1720 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);}
1722 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1724 r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1725 if (r_hlsl_permutation != perm)
1727 r_hlsl_permutation = perm;
1728 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1730 if (!r_hlsl_permutation->compiled)
1731 R_HLSL_CompilePermutation(perm, mode, permutation);
1732 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1734 // remove features until we find a valid permutation
1736 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1738 // reduce i more quickly whenever it would not remove any bits
1739 int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1740 if (!(permutation & j))
1743 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1744 if (!r_hlsl_permutation->compiled)
1745 R_HLSL_CompilePermutation(perm, mode, permutation);
1746 if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1749 if (i >= SHADERPERMUTATION_COUNT)
1751 //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1752 r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1753 return; // no bit left to clear, entire mode is broken
1757 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1758 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1760 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1761 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1762 hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1766 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1768 DPSOFTRAST_SetShader(mode, permutation);
1769 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1770 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1771 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1774 void R_GLSL_Restart_f(void)
1776 unsigned int i, limit;
1777 if (glslshaderstring && glslshaderstring != builtinshaderstring)
1778 Mem_Free(glslshaderstring);
1779 glslshaderstring = NULL;
1780 if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1781 Mem_Free(hlslshaderstring);
1782 hlslshaderstring = NULL;
1783 switch(vid.renderpath)
1785 case RENDERPATH_D3D9:
1788 r_hlsl_permutation_t *p;
1789 r_hlsl_permutation = NULL;
1790 limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1791 for (i = 0;i < limit;i++)
1793 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1795 if (p->vertexshader)
1796 IDirect3DVertexShader9_Release(p->vertexshader);
1798 IDirect3DPixelShader9_Release(p->pixelshader);
1799 Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1802 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1806 case RENDERPATH_D3D10:
1807 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1809 case RENDERPATH_D3D11:
1810 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1812 case RENDERPATH_GL20:
1813 case RENDERPATH_GLES2:
1815 r_glsl_permutation_t *p;
1816 r_glsl_permutation = NULL;
1817 limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1818 for (i = 0;i < limit;i++)
1820 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1822 GL_Backend_FreeProgram(p->program);
1823 Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1826 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1829 case RENDERPATH_GL13:
1830 case RENDERPATH_GL11:
1832 case RENDERPATH_SOFT:
1837 void R_GLSL_DumpShader_f(void)
1842 file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1845 FS_Print(file, "/* The engine may define the following macros:\n");
1846 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1847 for (i = 0;i < SHADERMODE_COUNT;i++)
1848 FS_Print(file, glslshadermodeinfo[i].pretext);
1849 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1850 FS_Print(file, shaderpermutationinfo[i].pretext);
1851 FS_Print(file, "*/\n");
1852 FS_Print(file, builtinshaderstring);
1854 Con_Printf("glsl/default.glsl written\n");
1857 Con_Printf("failed to write to glsl/default.glsl\n");
1859 file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1862 FS_Print(file, "/* The engine may define the following macros:\n");
1863 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1864 for (i = 0;i < SHADERMODE_COUNT;i++)
1865 FS_Print(file, hlslshadermodeinfo[i].pretext);
1866 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1867 FS_Print(file, shaderpermutationinfo[i].pretext);
1868 FS_Print(file, "*/\n");
1869 FS_Print(file, builtinhlslshaderstring);
1871 Con_Printf("hlsl/default.hlsl written\n");
1874 Con_Printf("failed to write to hlsl/default.hlsl\n");
1877 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
1880 texturemode = GL_MODULATE;
1881 switch (vid.renderpath)
1883 case RENDERPATH_D3D9:
1885 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))));
1886 R_Mesh_TexBind(GL20TU_FIRST , first );
1887 R_Mesh_TexBind(GL20TU_SECOND, second);
1890 case RENDERPATH_D3D10:
1891 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1893 case RENDERPATH_D3D11:
1894 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1896 case RENDERPATH_GL20:
1897 case RENDERPATH_GLES2:
1898 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))));
1899 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1900 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1902 case RENDERPATH_GL13:
1903 R_Mesh_TexBind(0, first );
1904 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1905 R_Mesh_TexBind(1, second);
1907 R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1909 case RENDERPATH_GL11:
1910 R_Mesh_TexBind(0, first );
1912 case RENDERPATH_SOFT:
1913 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))));
1914 R_Mesh_TexBind(GL20TU_FIRST , first );
1915 R_Mesh_TexBind(GL20TU_SECOND, second);
1920 void R_SetupShader_DepthOrShadow(void)
1922 switch (vid.renderpath)
1924 case RENDERPATH_D3D9:
1926 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1929 case RENDERPATH_D3D10:
1930 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1932 case RENDERPATH_D3D11:
1933 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1935 case RENDERPATH_GL20:
1936 case RENDERPATH_GLES2:
1937 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
1939 case RENDERPATH_GL13:
1940 R_Mesh_TexBind(0, 0);
1941 R_Mesh_TexBind(1, 0);
1943 case RENDERPATH_GL11:
1944 R_Mesh_TexBind(0, 0);
1946 case RENDERPATH_SOFT:
1947 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
1952 void R_SetupShader_ShowDepth(void)
1954 switch (vid.renderpath)
1956 case RENDERPATH_D3D9:
1958 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
1961 case RENDERPATH_D3D10:
1962 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1964 case RENDERPATH_D3D11:
1965 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1967 case RENDERPATH_GL20:
1968 case RENDERPATH_GLES2:
1969 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
1971 case RENDERPATH_GL13:
1973 case RENDERPATH_GL11:
1975 case RENDERPATH_SOFT:
1976 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
1981 extern qboolean r_shadow_usingdeferredprepass;
1982 extern cvar_t r_shadow_deferred_8bitrange;
1983 extern rtexture_t *r_shadow_attenuationgradienttexture;
1984 extern rtexture_t *r_shadow_attenuation2dtexture;
1985 extern rtexture_t *r_shadow_attenuation3dtexture;
1986 extern qboolean r_shadow_usingshadowmap2d;
1987 extern qboolean r_shadow_usingshadowmaportho;
1988 extern float r_shadow_shadowmap_texturescale[2];
1989 extern float r_shadow_shadowmap_parameters[4];
1990 extern qboolean r_shadow_shadowmapvsdct;
1991 extern qboolean r_shadow_shadowmapsampler;
1992 extern int r_shadow_shadowmappcf;
1993 extern rtexture_t *r_shadow_shadowmap2dtexture;
1994 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
1995 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
1996 extern matrix4x4_t r_shadow_shadowmapmatrix;
1997 extern int r_shadow_shadowmaplod; // changes for each light based on distance
1998 extern int r_shadow_prepass_width;
1999 extern int r_shadow_prepass_height;
2000 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2001 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2002 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2003 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2004 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2006 #define BLENDFUNC_ALLOWS_COLORMOD 1
2007 #define BLENDFUNC_ALLOWS_FOG 2
2008 #define BLENDFUNC_ALLOWS_FOG_HACK0 4
2009 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2010 #define BLENDFUNC_ALLOWS_ANYFOG (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2011 static int R_BlendFuncFlags(int src, int dst)
2015 // a blendfunc allows colormod if:
2016 // a) it can never keep the destination pixel invariant, or
2017 // b) it can keep the destination pixel invariant, and still can do so if colormodded
2018 // this is to prevent unintended side effects from colormod
2020 // a blendfunc allows fog if:
2021 // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2022 // this is to prevent unintended side effects from fog
2024 // these checks are the output of fogeval.pl
2026 r |= BLENDFUNC_ALLOWS_COLORMOD;
2027 if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2028 if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2029 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2030 if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2031 if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2032 if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2033 if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2034 if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2035 if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2036 if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2037 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2038 if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2039 if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2040 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2041 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2042 if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2043 if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2044 if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2045 if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2046 if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2047 if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2052 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)
2054 // select a permutation of the lighting shader appropriate to this
2055 // combination of texture, entity, light source, and fogging, only use the
2056 // minimum features necessary to avoid wasting rendering time in the
2057 // fragment shader on features that are not being used
2058 unsigned int permutation = 0;
2059 unsigned int mode = 0;
2061 static float dummy_colormod[3] = {1, 1, 1};
2062 float *colormod = rsurface.colormod;
2064 matrix4x4_t tempmatrix;
2065 r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2066 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2067 permutation |= SHADERPERMUTATION_ALPHAKILL;
2068 if (rsurfacepass == RSURFPASS_BACKGROUND)
2070 // distorted background
2071 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2073 mode = SHADERMODE_WATER;
2074 if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2075 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
2076 if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2078 // this is the right thing to do for wateralpha
2079 GL_BlendFunc(GL_ONE, GL_ZERO);
2080 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2084 // this is the right thing to do for entity alpha
2085 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2086 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2089 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2091 mode = SHADERMODE_REFRACTION;
2092 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2093 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2097 mode = SHADERMODE_GENERIC;
2098 permutation |= SHADERPERMUTATION_DIFFUSE;
2099 GL_BlendFunc(GL_ONE, GL_ZERO);
2100 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2103 else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2105 if (r_glsl_offsetmapping.integer)
2107 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2108 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2109 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2110 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2111 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2113 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2114 if (r_glsl_offsetmapping_reliefmapping.integer)
2115 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2118 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2119 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2120 // normalmap (deferred prepass), may use alpha test on diffuse
2121 mode = SHADERMODE_DEFERREDGEOMETRY;
2122 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2123 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2124 GL_BlendFunc(GL_ONE, GL_ZERO);
2125 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2127 else if (rsurfacepass == RSURFPASS_RTLIGHT)
2129 if (r_glsl_offsetmapping.integer)
2131 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2132 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2133 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2134 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2135 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2137 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2138 if (r_glsl_offsetmapping_reliefmapping.integer)
2139 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2142 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2143 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2145 mode = SHADERMODE_LIGHTSOURCE;
2146 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2147 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2148 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2149 permutation |= SHADERPERMUTATION_CUBEFILTER;
2150 if (diffusescale > 0)
2151 permutation |= SHADERPERMUTATION_DIFFUSE;
2152 if (specularscale > 0)
2153 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2154 if (r_refdef.fogenabled)
2155 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2156 if (rsurface.texture->colormapping)
2157 permutation |= SHADERPERMUTATION_COLORMAPPING;
2158 if (r_shadow_usingshadowmap2d)
2160 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2161 if(r_shadow_shadowmapvsdct)
2162 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2164 if (r_shadow_shadowmapsampler)
2165 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2166 if (r_shadow_shadowmappcf > 1)
2167 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2168 else if (r_shadow_shadowmappcf)
2169 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2171 if (rsurface.texture->reflectmasktexture)
2172 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2173 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2174 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2176 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2178 if (r_glsl_offsetmapping.integer)
2180 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2181 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2182 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2183 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2184 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2186 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2187 if (r_glsl_offsetmapping_reliefmapping.integer)
2188 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2191 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193 // unshaded geometry (fullbright or ambient model lighting)
2194 mode = SHADERMODE_FLATCOLOR;
2195 ambientscale = diffusescale = specularscale = 0;
2196 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2197 permutation |= SHADERPERMUTATION_GLOW;
2198 if (r_refdef.fogenabled)
2199 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2200 if (rsurface.texture->colormapping)
2201 permutation |= SHADERPERMUTATION_COLORMAPPING;
2202 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2204 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2205 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2207 if (r_shadow_shadowmapsampler)
2208 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2209 if (r_shadow_shadowmappcf > 1)
2210 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2211 else if (r_shadow_shadowmappcf)
2212 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2214 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2215 permutation |= SHADERPERMUTATION_REFLECTION;
2216 if (rsurface.texture->reflectmasktexture)
2217 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2218 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2219 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2221 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2223 if (r_glsl_offsetmapping.integer)
2225 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2226 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2227 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2228 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2229 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2231 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2232 if (r_glsl_offsetmapping_reliefmapping.integer)
2233 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2236 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2237 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2238 // directional model lighting
2239 mode = SHADERMODE_LIGHTDIRECTION;
2240 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2241 permutation |= SHADERPERMUTATION_GLOW;
2242 permutation |= SHADERPERMUTATION_DIFFUSE;
2243 if (specularscale > 0)
2244 permutation |= SHADERPERMUTATION_SPECULAR;
2245 if (r_refdef.fogenabled)
2246 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2247 if (rsurface.texture->colormapping)
2248 permutation |= SHADERPERMUTATION_COLORMAPPING;
2249 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2251 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2252 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2254 if (r_shadow_shadowmapsampler)
2255 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2256 if (r_shadow_shadowmappcf > 1)
2257 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2258 else if (r_shadow_shadowmappcf)
2259 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2261 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2262 permutation |= SHADERPERMUTATION_REFLECTION;
2263 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2264 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2265 if (rsurface.texture->reflectmasktexture)
2266 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2267 if (r_shadow_bouncegridtexture)
2269 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2270 if (r_shadow_bouncegriddirectional)
2271 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2273 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2276 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2278 if (r_glsl_offsetmapping.integer)
2280 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2281 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2282 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2283 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2284 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2286 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2287 if (r_glsl_offsetmapping_reliefmapping.integer)
2288 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2291 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2292 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2293 // ambient model lighting
2294 mode = SHADERMODE_LIGHTDIRECTION;
2295 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2296 permutation |= SHADERPERMUTATION_GLOW;
2297 if (r_refdef.fogenabled)
2298 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2299 if (rsurface.texture->colormapping)
2300 permutation |= SHADERPERMUTATION_COLORMAPPING;
2301 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2304 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306 if (r_shadow_shadowmapsampler)
2307 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2308 if (r_shadow_shadowmappcf > 1)
2309 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2310 else if (r_shadow_shadowmappcf)
2311 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2313 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2314 permutation |= SHADERPERMUTATION_REFLECTION;
2315 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2316 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2317 if (rsurface.texture->reflectmasktexture)
2318 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2319 if (r_shadow_bouncegridtexture)
2321 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2322 if (r_shadow_bouncegriddirectional)
2323 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2325 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2326 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2330 if (r_glsl_offsetmapping.integer)
2332 if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
2333 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2334 else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
2335 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2336 else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
2338 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
2339 if (r_glsl_offsetmapping_reliefmapping.integer)
2340 permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
2343 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2344 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2346 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2347 permutation |= SHADERPERMUTATION_GLOW;
2348 if (r_refdef.fogenabled)
2349 permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2350 if (rsurface.texture->colormapping)
2351 permutation |= SHADERPERMUTATION_COLORMAPPING;
2352 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2354 permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2355 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2357 if (r_shadow_shadowmapsampler)
2358 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2359 if (r_shadow_shadowmappcf > 1)
2360 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2361 else if (r_shadow_shadowmappcf)
2362 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2364 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2365 permutation |= SHADERPERMUTATION_REFLECTION;
2366 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2367 permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2368 if (rsurface.texture->reflectmasktexture)
2369 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2370 if (FAKELIGHT_ENABLED)
2372 // fake lightmapping (q1bsp, q3bsp, fullbright map)
2373 mode = SHADERMODE_FAKELIGHT;
2374 permutation |= SHADERPERMUTATION_DIFFUSE;
2375 if (specularscale > 0)
2376 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2378 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2380 // deluxemapping (light direction texture)
2381 if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2382 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2384 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2385 permutation |= SHADERPERMUTATION_DIFFUSE;
2386 if (specularscale > 0)
2387 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2389 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2391 // fake deluxemapping (uniform light direction in tangentspace)
2392 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2393 permutation |= SHADERPERMUTATION_DIFFUSE;
2394 if (specularscale > 0)
2395 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2397 else if (rsurface.uselightmaptexture)
2399 // ordinary lightmapping (q1bsp, q3bsp)
2400 mode = SHADERMODE_LIGHTMAP;
2404 // ordinary vertex coloring (q3bsp)
2405 mode = SHADERMODE_VERTEXCOLOR;
2407 if (r_shadow_bouncegridtexture)
2409 permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410 if (r_shadow_bouncegriddirectional)
2411 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416 if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2417 colormod = dummy_colormod;
2418 if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2419 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2420 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2421 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2422 switch(vid.renderpath)
2424 case RENDERPATH_D3D9:
2426 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);
2427 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2428 R_SetupShader_SetPermutationHLSL(mode, permutation);
2429 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2430 if (mode == SHADERMODE_LIGHTSOURCE)
2432 Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2433 hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2437 if (mode == SHADERMODE_LIGHTDIRECTION)
2439 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2442 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2443 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2444 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2445 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2446 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2448 if (mode == SHADERMODE_LIGHTSOURCE)
2450 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2451 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2452 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2453 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2454 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2456 // additive passes are only darkened by fog, not tinted
2457 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2458 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2462 if (mode == SHADERMODE_FLATCOLOR)
2464 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2466 else if (mode == SHADERMODE_LIGHTDIRECTION)
2468 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]);
2469 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2470 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);
2471 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);
2472 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2473 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2474 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2478 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2479 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2480 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);
2481 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);
2482 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2484 // additive passes are only darkened by fog, not tinted
2485 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2486 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2488 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2489 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);
2490 hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2491 hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2492 hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2493 hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2494 hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2495 hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2496 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2497 if (mode == SHADERMODE_WATER)
2498 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2500 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2501 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2502 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2503 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));
2504 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2505 if (rsurface.texture->pantstexture)
2506 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2508 hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2509 if (rsurface.texture->shirttexture)
2510 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2512 hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2513 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2514 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2515 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2516 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2517 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));
2518 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2519 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2521 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2522 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2523 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2524 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2525 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2526 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2527 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2528 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2529 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2530 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2531 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2532 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2533 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2534 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2535 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2536 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2537 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2538 if (rsurfacepass == RSURFPASS_BACKGROUND)
2540 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2541 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2542 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2546 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2548 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2549 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2550 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2551 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2552 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2554 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2555 if (rsurface.rtlight)
2557 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2558 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2563 case RENDERPATH_D3D10:
2564 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2566 case RENDERPATH_D3D11:
2567 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2569 case RENDERPATH_GL20:
2570 case RENDERPATH_GLES2:
2571 if (!vid.useinterleavedarrays)
2573 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);
2574 R_Mesh_VertexPointer( 3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2575 R_Mesh_ColorPointer( 4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2576 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2577 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2578 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2579 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2580 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2584 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);
2585 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2587 R_SetupShader_SetPermutationGLSL(mode, permutation);
2588 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2589 if (mode == SHADERMODE_LIGHTSOURCE)
2591 if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2592 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2593 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2594 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2595 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2596 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);
2598 // additive passes are only darkened by fog, not tinted
2599 if (r_glsl_permutation->loc_FogColor >= 0)
2600 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2601 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605 if (mode == SHADERMODE_FLATCOLOR)
2607 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2609 else if (mode == SHADERMODE_LIGHTDIRECTION)
2611 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]);
2612 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]);
2613 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);
2614 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);
2615 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);
2616 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]);
2617 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]);
2621 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]);
2622 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]);
2623 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2624 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2625 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2627 // additive passes are only darkened by fog, not tinted
2628 if (r_glsl_permutation->loc_FogColor >= 0)
2630 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2631 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2633 qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2635 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);
2636 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]);
2637 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]);
2638 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]);
2639 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]);
2640 if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2641 if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2642 if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2643 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]);
2645 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2646 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2647 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2648 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]);
2649 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]);
2651 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2652 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));
2653 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2654 if (r_glsl_permutation->loc_Color_Pants >= 0)
2656 if (rsurface.texture->pantstexture)
2657 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2659 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2661 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2663 if (rsurface.texture->shirttexture)
2664 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2666 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2668 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]);
2669 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2670 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2671 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2672 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));
2673 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]);
2674 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2675 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);}
2676 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
2678 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_texture_white );
2679 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_texture_white );
2680 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps , r_texture_gammaramps );
2681 if (r_glsl_permutation->tex_Texture_Normal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal , rsurface.texture->nmaptexture );
2682 if (r_glsl_permutation->tex_Texture_Color >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color , rsurface.texture->basetexture );
2683 if (r_glsl_permutation->tex_Texture_Gloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss , rsurface.texture->glosstexture );
2684 if (r_glsl_permutation->tex_Texture_Glow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow , rsurface.texture->glowtexture );
2685 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal , rsurface.texture->backgroundnmaptexture );
2686 if (r_glsl_permutation->tex_Texture_SecondaryColor >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture );
2687 if (r_glsl_permutation->tex_Texture_SecondaryGloss >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture );
2688 if (r_glsl_permutation->tex_Texture_SecondaryGlow >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow , rsurface.texture->backgroundglowtexture );
2689 if (r_glsl_permutation->tex_Texture_Pants >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants , rsurface.texture->pantstexture );
2690 if (r_glsl_permutation->tex_Texture_Shirt >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt , rsurface.texture->shirttexture );
2691 if (r_glsl_permutation->tex_Texture_ReflectMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask , rsurface.texture->reflectmasktexture );
2692 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);
2693 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture );
2694 if (r_glsl_permutation->tex_Texture_FogMask >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask , r_texture_fogattenuation );
2695 if (r_glsl_permutation->tex_Texture_Lightmap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2696 if (r_glsl_permutation->tex_Texture_Deluxemap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2697 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2698 if (rsurfacepass == RSURFPASS_BACKGROUND)
2700 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);
2701 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);
2702 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);
2706 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);
2708 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2709 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2710 if (r_glsl_permutation->tex_Texture_ScreenDiffuse >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse , r_shadow_prepasslightingdiffusetexture );
2711 if (r_glsl_permutation->tex_Texture_ScreenSpecular >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture );
2712 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2714 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture );
2715 if (rsurface.rtlight)
2717 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2718 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2721 if (r_glsl_permutation->tex_Texture_BounceGrid >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2724 case RENDERPATH_GL13:
2725 case RENDERPATH_GL11:
2727 case RENDERPATH_SOFT:
2728 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);
2729 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2730 R_SetupShader_SetPermutationSoft(mode, permutation);
2731 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2732 if (mode == SHADERMODE_LIGHTSOURCE)
2734 {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2735 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2736 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2737 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2738 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2739 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2741 // additive passes are only darkened by fog, not tinted
2742 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2743 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2747 if (mode == SHADERMODE_FLATCOLOR)
2749 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2751 else if (mode == SHADERMODE_LIGHTDIRECTION)
2753 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]);
2754 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2755 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);
2756 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);
2757 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2758 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]);
2759 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2763 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2764 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2765 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);
2766 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);
2767 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2769 // additive passes are only darkened by fog, not tinted
2770 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2771 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2773 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2774 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);
2775 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2776 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2777 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]);
2778 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]);
2779 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2780 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2781 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2782 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2784 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2785 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2786 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2787 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2788 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]);
2790 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2791 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));
2792 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2793 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2795 if (rsurface.texture->pantstexture)
2796 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2798 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2800 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2802 if (rsurface.texture->shirttexture)
2803 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2805 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2807 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2808 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2809 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2810 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2811 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));
2812 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2813 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2815 R_Mesh_TexBind(GL20TU_NORMAL , rsurface.texture->nmaptexture );
2816 R_Mesh_TexBind(GL20TU_COLOR , rsurface.texture->basetexture );
2817 R_Mesh_TexBind(GL20TU_GLOSS , rsurface.texture->glosstexture );
2818 R_Mesh_TexBind(GL20TU_GLOW , rsurface.texture->glowtexture );
2819 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL , rsurface.texture->backgroundnmaptexture );
2820 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR , rsurface.texture->backgroundbasetexture );
2821 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS , rsurface.texture->backgroundglosstexture );
2822 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW , rsurface.texture->backgroundglowtexture );
2823 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS , rsurface.texture->pantstexture );
2824 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT , rsurface.texture->shirttexture );
2825 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK , rsurface.texture->reflectmasktexture );
2826 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2827 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE , r_texture_fogheighttexture );
2828 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK , r_texture_fogattenuation );
2829 R_Mesh_TexBind(GL20TU_LIGHTMAP , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2830 R_Mesh_TexBind(GL20TU_DELUXEMAP , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2831 if (rsurface.rtlight ) R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2832 if (rsurfacepass == RSURFPASS_BACKGROUND)
2834 R_Mesh_TexBind(GL20TU_REFRACTION , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2835 if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2836 R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2840 if (permutation & SHADERPERMUTATION_REFLECTION ) R_Mesh_TexBind(GL20TU_REFLECTION , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2842 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2843 // if (rsurfacepass == RSURFPASS_DEFERREDLIGHT ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2844 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE , r_shadow_prepasslightingdiffusetexture );
2845 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR , r_shadow_prepasslightingspeculartexture );
2846 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2848 R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2849 if (rsurface.rtlight)
2851 if (permutation & SHADERPERMUTATION_CUBEFILTER ) R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2852 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2859 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2861 // select a permutation of the lighting shader appropriate to this
2862 // combination of texture, entity, light source, and fogging, only use the
2863 // minimum features necessary to avoid wasting rendering time in the
2864 // fragment shader on features that are not being used
2865 unsigned int permutation = 0;
2866 unsigned int mode = 0;
2867 const float *lightcolorbase = rtlight->currentcolor;
2868 float ambientscale = rtlight->ambientscale;
2869 float diffusescale = rtlight->diffusescale;
2870 float specularscale = rtlight->specularscale;
2871 // this is the location of the light in view space
2872 vec3_t viewlightorigin;
2873 // this transforms from view space (camera) to light space (cubemap)
2874 matrix4x4_t viewtolight;
2875 matrix4x4_t lighttoview;
2876 float viewtolight16f[16];
2877 float range = 1.0f / r_shadow_deferred_8bitrange.value;
2879 mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2880 if (rtlight->currentcubemap != r_texture_whitecube)
2881 permutation |= SHADERPERMUTATION_CUBEFILTER;
2882 if (diffusescale > 0)
2883 permutation |= SHADERPERMUTATION_DIFFUSE;
2884 if (specularscale > 0)
2885 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2886 if (r_shadow_usingshadowmap2d)
2888 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2889 if (r_shadow_shadowmapvsdct)
2890 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2892 if (r_shadow_shadowmapsampler)
2893 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2894 if (r_shadow_shadowmappcf > 1)
2895 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2896 else if (r_shadow_shadowmappcf)
2897 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2899 Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2900 Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2901 Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
2902 Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
2903 switch(vid.renderpath)
2905 case RENDERPATH_D3D9:
2907 R_SetupShader_SetPermutationHLSL(mode, permutation);
2908 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2909 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
2910 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2911 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2912 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2913 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2914 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2915 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2916 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2917 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2919 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2920 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthcolortexture );
2921 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2922 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2923 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dcolortexture );
2924 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2927 case RENDERPATH_D3D10:
2928 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2930 case RENDERPATH_D3D11:
2931 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2933 case RENDERPATH_GL20:
2934 case RENDERPATH_GLES2:
2935 R_SetupShader_SetPermutationGLSL(mode, permutation);
2936 if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f( r_glsl_permutation->loc_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2937 if (r_glsl_permutation->loc_ViewToLight >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight , 1, false, viewtolight16f);
2938 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);
2939 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);
2940 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);
2941 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]);
2942 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]);
2943 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));
2944 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]);
2945 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f( r_glsl_permutation->loc_PixelToScreenTexCoord , 1.0f/vid.width, 1.0f/vid.height);
2947 if (r_glsl_permutation->tex_Texture_Attenuation >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation , r_shadow_attenuationgradienttexture );
2948 if (r_glsl_permutation->tex_Texture_ScreenDepth >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth , r_shadow_prepassgeometrydepthtexture );
2949 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap , r_shadow_prepassgeometrynormalmaptexture );
2950 if (r_glsl_permutation->tex_Texture_Cube >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube , rsurface.rtlight->currentcubemap );
2951 if (r_glsl_permutation->tex_Texture_ShadowMap2D >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D , r_shadow_shadowmap2dtexture );
2952 if (r_glsl_permutation->tex_Texture_CubeProjection >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture );
2954 case RENDERPATH_GL13:
2955 case RENDERPATH_GL11:
2957 case RENDERPATH_SOFT:
2958 R_SetupShader_SetPermutationGLSL(mode, permutation);
2959 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_LightPosition , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
2960 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1 , 1, false, viewtolight16f);
2961 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Ambient , lightcolorbase[0] * ambientscale * range, lightcolorbase[1] * ambientscale * range, lightcolorbase[2] * ambientscale * range);
2962 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale * range, lightcolorbase[1] * diffusescale * range, lightcolorbase[2] * diffusescale * range);
2963 DPSOFTRAST_Uniform3f( DPSOFTRAST_UNIFORM_DeferredColor_Specular , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
2964 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ShadowMap_TextureScale , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2965 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]);
2966 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));
2967 DPSOFTRAST_Uniform2f( DPSOFTRAST_UNIFORM_ScreenToDepth , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2968 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2970 R_Mesh_TexBind(GL20TU_ATTENUATION , r_shadow_attenuationgradienttexture );
2971 R_Mesh_TexBind(GL20TU_SCREENDEPTH , r_shadow_prepassgeometrydepthtexture );
2972 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP , r_shadow_prepassgeometrynormalmaptexture );
2973 R_Mesh_TexBind(GL20TU_CUBE , rsurface.rtlight->currentcubemap );
2974 R_Mesh_TexBind(GL20TU_SHADOWMAP2D , r_shadow_shadowmap2dtexture );
2975 R_Mesh_TexBind(GL20TU_CUBEPROJECTION , r_shadow_shadowmapvsdcttexture );
2980 #define SKINFRAME_HASH 1024
2984 int loadsequence; // incremented each level change
2985 memexpandablearray_t array;
2986 skinframe_t *hash[SKINFRAME_HASH];
2989 r_skinframe_t r_skinframe;
2991 void R_SkinFrame_PrepareForPurge(void)
2993 r_skinframe.loadsequence++;
2994 // wrap it without hitting zero
2995 if (r_skinframe.loadsequence >= 200)
2996 r_skinframe.loadsequence = 1;
2999 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3003 // mark the skinframe as used for the purging code
3004 skinframe->loadsequence = r_skinframe.loadsequence;
3007 void R_SkinFrame_Purge(void)
3011 for (i = 0;i < SKINFRAME_HASH;i++)
3013 for (s = r_skinframe.hash[i];s;s = s->next)
3015 if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3017 if (s->merged == s->base)
3019 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3020 R_PurgeTexture(s->stain );s->stain = NULL;
3021 R_PurgeTexture(s->merged);s->merged = NULL;
3022 R_PurgeTexture(s->base );s->base = NULL;
3023 R_PurgeTexture(s->pants );s->pants = NULL;
3024 R_PurgeTexture(s->shirt );s->shirt = NULL;
3025 R_PurgeTexture(s->nmap );s->nmap = NULL;
3026 R_PurgeTexture(s->gloss );s->gloss = NULL;
3027 R_PurgeTexture(s->glow );s->glow = NULL;
3028 R_PurgeTexture(s->fog );s->fog = NULL;
3029 R_PurgeTexture(s->reflect);s->reflect = NULL;
3030 s->loadsequence = 0;
3036 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3038 char basename[MAX_QPATH];
3040 Image_StripImageExtension(name, basename, sizeof(basename));
3042 if( last == NULL ) {
3044 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3045 item = r_skinframe.hash[hashindex];
3050 // linearly search through the hash bucket
3051 for( ; item ; item = item->next ) {
3052 if( !strcmp( item->basename, basename ) ) {
3059 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3063 char basename[MAX_QPATH];
3065 Image_StripImageExtension(name, basename, sizeof(basename));
3067 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3068 for (item = r_skinframe.hash[hashindex];item;item = item->next)
3069 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3073 rtexture_t *dyntexture;
3074 // check whether its a dynamic texture
3075 dyntexture = CL_GetDynTexture( basename );
3076 if (!add && !dyntexture)
3078 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3079 memset(item, 0, sizeof(*item));
3080 strlcpy(item->basename, basename, sizeof(item->basename));
3081 item->base = dyntexture; // either NULL or dyntexture handle
3082 item->textureflags = textureflags;
3083 item->comparewidth = comparewidth;
3084 item->compareheight = compareheight;
3085 item->comparecrc = comparecrc;
3086 item->next = r_skinframe.hash[hashindex];
3087 r_skinframe.hash[hashindex] = item;
3089 else if( item->base == NULL )
3091 rtexture_t *dyntexture;
3092 // check whether its a dynamic texture
3093 // 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]
3094 dyntexture = CL_GetDynTexture( basename );
3095 item->base = dyntexture; // either NULL or dyntexture handle
3098 R_SkinFrame_MarkUsed(item);
3102 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3104 unsigned long long avgcolor[5], wsum; \
3112 for(pix = 0; pix < cnt; ++pix) \
3115 for(comp = 0; comp < 3; ++comp) \
3117 if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3120 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3122 for(comp = 0; comp < 3; ++comp) \
3123 avgcolor[comp] += getpixel * w; \
3126 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3127 avgcolor[4] += getpixel; \
3129 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3131 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3132 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3133 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3134 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3137 extern cvar_t gl_picmip;
3138 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3141 unsigned char *pixels;
3142 unsigned char *bumppixels;
3143 unsigned char *basepixels = NULL;
3144 int basepixels_width = 0;
3145 int basepixels_height = 0;
3146 skinframe_t *skinframe;
3147 rtexture_t *ddsbase = NULL;
3148 qboolean ddshasalpha = false;
3149 float ddsavgcolor[4];
3150 char basename[MAX_QPATH];
3151 int miplevel = R_PicmipForFlags(textureflags);
3152 int savemiplevel = miplevel;
3155 if (cls.state == ca_dedicated)
3158 // return an existing skinframe if already loaded
3159 // if loading of the first image fails, don't make a new skinframe as it
3160 // would cause all future lookups of this to be missing
3161 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3162 if (skinframe && skinframe->base)
3165 Image_StripImageExtension(name, basename, sizeof(basename));
3167 // check for DDS texture file first
3168 if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3170 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
3171 if (basepixels == NULL)
3175 // FIXME handle miplevel
3177 if (developer_loading.integer)
3178 Con_Printf("loading skin \"%s\"\n", name);
3180 // we've got some pixels to store, so really allocate this new texture now
3182 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3183 skinframe->stain = NULL;
3184 skinframe->merged = NULL;
3185 skinframe->base = NULL;
3186 skinframe->pants = NULL;
3187 skinframe->shirt = NULL;
3188 skinframe->nmap = NULL;
3189 skinframe->gloss = NULL;
3190 skinframe->glow = NULL;
3191 skinframe->fog = NULL;
3192 skinframe->reflect = NULL;
3193 skinframe->hasalpha = false;
3197 skinframe->base = ddsbase;
3198 skinframe->hasalpha = ddshasalpha;
3199 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3200 if (r_loadfog && skinframe->hasalpha)
3201 skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3202 //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]);
3206 basepixels_width = image_width;
3207 basepixels_height = image_height;
3208 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);
3209 if (textureflags & TEXF_ALPHA)
3211 for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3213 if (basepixels[j] < 255)
3215 skinframe->hasalpha = true;
3219 if (r_loadfog && skinframe->hasalpha)
3221 // has transparent pixels
3222 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3223 for (j = 0;j < image_width * image_height * 4;j += 4)
3228 pixels[j+3] = basepixels[j+3];
3230 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);
3234 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3235 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3236 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3237 R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
3238 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3239 R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
3244 mymiplevel = savemiplevel;
3245 if (r_loadnormalmap)
3246 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);
3247 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3249 skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3250 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3251 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3252 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3255 // _norm is the name used by tenebrae and has been adopted as standard
3256 if (r_loadnormalmap && skinframe->nmap == NULL)
3258 mymiplevel = savemiplevel;
3259 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3261 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);
3265 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3267 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3268 Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3269 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);
3271 Mem_Free(bumppixels);
3273 else if (r_shadow_bumpscale_basetexture.value > 0)
3275 pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3276 Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3277 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);
3280 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3281 R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
3284 // _luma is supported only for tenebrae compatibility
3285 // _glow is the preferred name
3286 mymiplevel = savemiplevel;
3287 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))))
3289 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);
3290 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3291 R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
3292 Mem_Free(pixels);pixels = NULL;
3295 mymiplevel = savemiplevel;
3296 if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3298 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);
3299 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3300 R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
3305 mymiplevel = savemiplevel;
3306 if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3308 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);
3309 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3310 R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
3315 mymiplevel = savemiplevel;
3316 if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3318 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);
3319 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3320 R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
3325 mymiplevel = savemiplevel;
3326 if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
3328 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);
3329 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3330 R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
3336 Mem_Free(basepixels);
3341 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3342 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
3345 unsigned char *temp1, *temp2;
3346 skinframe_t *skinframe;
3348 if (cls.state == ca_dedicated)
3351 // if already loaded just return it, otherwise make a new skinframe
3352 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3353 if (skinframe && skinframe->base)
3356 skinframe->stain = NULL;
3357 skinframe->merged = NULL;
3358 skinframe->base = NULL;
3359 skinframe->pants = NULL;
3360 skinframe->shirt = NULL;
3361 skinframe->nmap = NULL;
3362 skinframe->gloss = NULL;
3363 skinframe->glow = NULL;
3364 skinframe->fog = NULL;
3365 skinframe->reflect = NULL;
3366 skinframe->hasalpha = false;
3368 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3372 if (developer_loading.integer)
3373 Con_Printf("loading 32bit skin \"%s\"\n", name);
3375 if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3377 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3378 temp2 = temp1 + width * height * 4;
3379 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3380 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);
3383 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
3384 if (textureflags & TEXF_ALPHA)
3386 for (i = 3;i < width * height * 4;i += 4)
3388 if (skindata[i] < 255)
3390 skinframe->hasalpha = true;
3394 if (r_loadfog && skinframe->hasalpha)
3396 unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3397 memcpy(fogpixels, skindata, width * height * 4);
3398 for (i = 0;i < width * height * 4;i += 4)
3399 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3400 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3401 Mem_Free(fogpixels);
3405 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3406 //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]);
3411 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3415 skinframe_t *skinframe;
3417 if (cls.state == ca_dedicated)
3420 // if already loaded just return it, otherwise make a new skinframe
3421 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3422 if (skinframe && skinframe->base)
3425 skinframe->stain = NULL;
3426 skinframe->merged = NULL;
3427 skinframe->base = NULL;
3428 skinframe->pants = NULL;
3429 skinframe->shirt = NULL;
3430 skinframe->nmap = NULL;
3431 skinframe->gloss = NULL;
3432 skinframe->glow = NULL;
3433 skinframe->fog = NULL;
3434 skinframe->reflect = NULL;
3435 skinframe->hasalpha = false;
3437 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3441 if (developer_loading.integer)
3442 Con_Printf("loading quake skin \"%s\"\n", name);
3444 // 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)
3445 skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3446 memcpy(skinframe->qpixels, skindata, width*height);
3447 skinframe->qwidth = width;
3448 skinframe->qheight = height;
3451 for (i = 0;i < width * height;i++)
3452 featuresmask |= palette_featureflags[skindata[i]];
3454 skinframe->hasalpha = false;
3455 skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3456 skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3457 skinframe->qgeneratemerged = true;
3458 skinframe->qgeneratebase = skinframe->qhascolormapping;
3459 skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3461 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3462 //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]);
3467 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3471 unsigned char *skindata;
3473 if (!skinframe->qpixels)
3476 if (!skinframe->qhascolormapping)
3477 colormapped = false;
3481 if (!skinframe->qgeneratebase)
3486 if (!skinframe->qgeneratemerged)
3490 width = skinframe->qwidth;
3491 height = skinframe->qheight;
3492 skindata = skinframe->qpixels;
3494 if (skinframe->qgeneratenmap)
3496 unsigned char *temp1, *temp2;
3497 skinframe->qgeneratenmap = false;
3498 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3499 temp2 = temp1 + width * height * 4;
3500 // use either a custom palette or the quake palette
3501 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3502 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3503 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);
3507 if (skinframe->qgenerateglow)
3509 skinframe->qgenerateglow = false;
3510 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3515 skinframe->qgeneratebase = false;
3516 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);
3517 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3518 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3522 skinframe->qgeneratemerged = false;
3523 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);
3526 if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3528 Mem_Free(skinframe->qpixels);
3529 skinframe->qpixels = NULL;
3533 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)
3536 skinframe_t *skinframe;
3538 if (cls.state == ca_dedicated)
3541 // if already loaded just return it, otherwise make a new skinframe
3542 skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3543 if (skinframe && skinframe->base)
3546 skinframe->stain = NULL;
3547 skinframe->merged = NULL;
3548 skinframe->base = NULL;
3549 skinframe->pants = NULL;
3550 skinframe->shirt = NULL;
3551 skinframe->nmap = NULL;
3552 skinframe->gloss = NULL;
3553 skinframe->glow = NULL;
3554 skinframe->fog = NULL;
3555 skinframe->reflect = NULL;
3556 skinframe->hasalpha = false;
3558 // if no data was provided, then clearly the caller wanted to get a blank skinframe
3562 if (developer_loading.integer)
3563 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3565 skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3566 if (textureflags & TEXF_ALPHA)
3568 for (i = 0;i < width * height;i++)
3570 if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3572 skinframe->hasalpha = true;
3576 if (r_loadfog && skinframe->hasalpha)
3577 skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3580 R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3581 //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]);
3586 skinframe_t *R_SkinFrame_LoadMissing(void)
3588 skinframe_t *skinframe;
3590 if (cls.state == ca_dedicated)
3593 skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3594 skinframe->stain = NULL;
3595 skinframe->merged = NULL;
3596 skinframe->base = NULL;
3597 skinframe->pants = NULL;
3598 skinframe->shirt = NULL;
3599 skinframe->nmap = NULL;
3600 skinframe->gloss = NULL;
3601 skinframe->glow = NULL;
3602 skinframe->fog = NULL;
3603 skinframe->reflect = NULL;
3604 skinframe->hasalpha = false;
3606 skinframe->avgcolor[0] = rand() / RAND_MAX;
3607 skinframe->avgcolor[1] = rand() / RAND_MAX;
3608 skinframe->avgcolor[2] = rand() / RAND_MAX;
3609 skinframe->avgcolor[3] = 1;
3614 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3615 typedef struct suffixinfo_s
3618 qboolean flipx, flipy, flipdiagonal;
3621 static suffixinfo_t suffix[3][6] =
3624 {"px", false, false, false},
3625 {"nx", false, false, false},
3626 {"py", false, false, false},
3627 {"ny", false, false, false},
3628 {"pz", false, false, false},
3629 {"nz", false, false, false}
3632 {"posx", false, false, false},
3633 {"negx", false, false, false},
3634 {"posy", false, false, false},
3635 {"negy", false, false, false},
3636 {"posz", false, false, false},
3637 {"negz", false, false, false}
3640 {"rt", true, false, true},
3641 {"lf", false, true, true},
3642 {"ft", true, true, false},
3643 {"bk", false, false, false},
3644 {"up", true, false, true},
3645 {"dn", true, false, true}
3649 static int componentorder[4] = {0, 1, 2, 3};
3651 rtexture_t *R_LoadCubemap(const char *basename)
3653 int i, j, cubemapsize;
3654 unsigned char *cubemappixels, *image_buffer;
3655 rtexture_t *cubemaptexture;
3657 // must start 0 so the first loadimagepixels has no requested width/height
3659 cubemappixels = NULL;
3660 cubemaptexture = NULL;
3661 // keep trying different suffix groups (posx, px, rt) until one loads
3662 for (j = 0;j < 3 && !cubemappixels;j++)
3664 // load the 6 images in the suffix group
3665 for (i = 0;i < 6;i++)
3667 // generate an image name based on the base and and suffix
3668 dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3670 if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
3672 // an image loaded, make sure width and height are equal
3673 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3675 // if this is the first image to load successfully, allocate the cubemap memory
3676 if (!cubemappixels && image_width >= 1)
3678 cubemapsize = image_width;
3679 // note this clears to black, so unavailable sides are black
3680 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3682 // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3684 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);
3687 Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3689 Mem_Free(image_buffer);
3693 // if a cubemap loaded, upload it
3696 if (developer_loading.integer)
3697 Con_Printf("loading cubemap \"%s\"\n", basename);
3699 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3700 Mem_Free(cubemappixels);
3704 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3705 if (developer_loading.integer)
3707 Con_Printf("(tried tried images ");
3708 for (j = 0;j < 3;j++)
3709 for (i = 0;i < 6;i++)
3710 Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3711 Con_Print(" and was unable to find any of them).\n");
3714 return cubemaptexture;
3717 rtexture_t *R_GetCubemap(const char *basename)
3720 for (i = 0;i < r_texture_numcubemaps;i++)
3721 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
3722 return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
3723 if (i >= MAX_CUBEMAPS)
3724 return r_texture_whitecube;
3725 r_texture_numcubemaps++;
3726 strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
3727 r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
3728 return r_texture_cubemaps[i].texture;
3731 void R_FreeCubemaps(void)
3734 for (i = 0;i < r_texture_numcubemaps;i++)
3736 if (developer_loading.integer)
3737 Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
3738 if (r_texture_cubemaps[i].texture)
3739 R_FreeTexture(r_texture_cubemaps[i].texture);
3741 r_texture_numcubemaps = 0;
3744 void R_Main_FreeViewCache(void)
3746 if (r_refdef.viewcache.entityvisible)
3747 Mem_Free(r_refdef.viewcache.entityvisible);
3748 if (r_refdef.viewcache.world_pvsbits)
3749 Mem_Free(r_refdef.viewcache.world_pvsbits);
3750 if (r_refdef.viewcache.world_leafvisible)
3751 Mem_Free(r_refdef.viewcache.world_leafvisible);
3752 if (r_refdef.viewcache.world_surfacevisible)
3753 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3754 memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3757 void R_Main_ResizeViewCache(void)
3759 int numentities = r_refdef.scene.numentities;
3760 int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3761 int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3762 int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3763 int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3764 if (r_refdef.viewcache.maxentities < numentities)
3766 r_refdef.viewcache.maxentities = numentities;
3767 if (r_refdef.viewcache.entityvisible)
3768 Mem_Free(r_refdef.viewcache.entityvisible);
3769 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3771 if (r_refdef.viewcache.world_numclusters != numclusters)
3773 r_refdef.viewcache.world_numclusters = numclusters;
3774 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3775 if (r_refdef.viewcache.world_pvsbits)
3776 Mem_Free(r_refdef.viewcache.world_pvsbits);
3777 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3779 if (r_refdef.viewcache.world_numleafs != numleafs)
3781 r_refdef.viewcache.world_numleafs = numleafs;
3782 if (r_refdef.viewcache.world_leafvisible)
3783 Mem_Free(r_refdef.viewcache.world_leafvisible);
3784 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3786 if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3788 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3789 if (r_refdef.viewcache.world_surfacevisible)
3790 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3791 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3795 extern rtexture_t *loadingscreentexture;
3796 void gl_main_start(void)
3798 loadingscreentexture = NULL;
3799 r_texture_blanknormalmap = NULL;
3800 r_texture_white = NULL;
3801 r_texture_grey128 = NULL;
3802 r_texture_black = NULL;
3803 r_texture_whitecube = NULL;
3804 r_texture_normalizationcube = NULL;
3805 r_texture_fogattenuation = NULL;
3806 r_texture_fogheighttexture = NULL;
3807 r_texture_gammaramps = NULL;
3808 r_texture_numcubemaps = 0;
3810 r_loaddds = r_texture_dds_load.integer != 0;
3811 r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3813 switch(vid.renderpath)
3815 case RENDERPATH_GL20:
3816 case RENDERPATH_D3D9:
3817 case RENDERPATH_D3D10:
3818 case RENDERPATH_D3D11:
3819 case RENDERPATH_SOFT:
3820 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3821 Cvar_SetValueQuick(&gl_combine, 1);
3822 Cvar_SetValueQuick(&r_glsl, 1);
3823 r_loadnormalmap = true;
3827 case RENDERPATH_GL13:
3828 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3829 Cvar_SetValueQuick(&gl_combine, 1);
3830 Cvar_SetValueQuick(&r_glsl, 0);
3831 r_loadnormalmap = false;
3832 r_loadgloss = false;
3835 case RENDERPATH_GL11:
3836 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3837 Cvar_SetValueQuick(&gl_combine, 0);
3838 Cvar_SetValueQuick(&r_glsl, 0);
3839 r_loadnormalmap = false;
3840 r_loadgloss = false;
3843 case RENDERPATH_GLES2:
3844 Cvar_SetValueQuick(&r_textureunits, 1);
3845 Cvar_SetValueQuick(&gl_combine, 1);
3846 Cvar_SetValueQuick(&r_glsl, 1);
3847 r_loadnormalmap = true;
3848 r_loadgloss = false;
3854 R_FrameData_Reset();
3858 memset(r_queries, 0, sizeof(r_queries));
3860 r_qwskincache = NULL;
3861 r_qwskincache_size = 0;
3863 // due to caching of texture_t references, the collision cache must be reset
3864 Collision_Cache_Reset(true);
3866 // set up r_skinframe loading system for textures
3867 memset(&r_skinframe, 0, sizeof(r_skinframe));
3868 r_skinframe.loadsequence = 1;
3869 Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3871 r_main_texturepool = R_AllocTexturePool();
3872 R_BuildBlankTextures();
3874 if (vid.support.arb_texture_cube_map)
3877 R_BuildNormalizationCube();
3879 r_texture_fogattenuation = NULL;
3880 r_texture_fogheighttexture = NULL;
3881 r_texture_gammaramps = NULL;
3882 //r_texture_fogintensity = NULL;
3883 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3884 memset(&r_waterstate, 0, sizeof(r_waterstate));
3885 r_glsl_permutation = NULL;
3886 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3887 Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
3888 glslshaderstring = NULL;
3890 r_hlsl_permutation = NULL;
3891 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3892 Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
3894 hlslshaderstring = NULL;
3895 memset(&r_svbsp, 0, sizeof (r_svbsp));
3897 r_refdef.fogmasktable_density = 0;
3900 void gl_main_shutdown(void)
3903 R_FrameData_Reset();
3905 R_Main_FreeViewCache();
3907 switch(vid.renderpath)
3909 case RENDERPATH_GL11:
3910 case RENDERPATH_GL13:
3911 case RENDERPATH_GL20:
3912 case RENDERPATH_GLES2:
3914 qglDeleteQueriesARB(r_maxqueries, r_queries);
3916 case RENDERPATH_D3D9:
3917 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3919 case RENDERPATH_D3D10:
3920 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3922 case RENDERPATH_D3D11:
3923 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3925 case RENDERPATH_SOFT:
3931 memset(r_queries, 0, sizeof(r_queries));
3933 r_qwskincache = NULL;
3934 r_qwskincache_size = 0;
3936 // clear out the r_skinframe state
3937 Mem_ExpandableArray_FreeArray(&r_skinframe.array);
3938 memset(&r_skinframe, 0, sizeof(r_skinframe));
3941 Mem_Free(r_svbsp.nodes);
3942 memset(&r_svbsp, 0, sizeof (r_svbsp));
3943 R_FreeTexturePool(&r_main_texturepool);
3944 loadingscreentexture = NULL;
3945 r_texture_blanknormalmap = NULL;
3946 r_texture_white = NULL;
3947 r_texture_grey128 = NULL;
3948 r_texture_black = NULL;
3949 r_texture_whitecube = NULL;
3950 r_texture_normalizationcube = NULL;
3951 r_texture_fogattenuation = NULL;
3952 r_texture_fogheighttexture = NULL;
3953 r_texture_gammaramps = NULL;
3954 r_texture_numcubemaps = 0;
3955 //r_texture_fogintensity = NULL;
3956 memset(&r_bloomstate, 0, sizeof(r_bloomstate));
3957 memset(&r_waterstate, 0, sizeof(r_waterstate));
3960 r_glsl_permutation = NULL;
3961 memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
3962 Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
3963 glslshaderstring = NULL;
3965 r_hlsl_permutation = NULL;
3966 memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
3967 Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
3969 hlslshaderstring = NULL;
3972 extern void CL_ParseEntityLump(char *entitystring);
3973 void gl_main_newmap(void)
3975 // FIXME: move this code to client
3976 char *entities, entname[MAX_QPATH];
3978 Mem_Free(r_qwskincache);
3979 r_qwskincache = NULL;
3980 r_qwskincache_size = 0;
3983 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
3984 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
3986 CL_ParseEntityLump(entities);
3990 if (cl.worldmodel->brush.entities)
3991 CL_ParseEntityLump(cl.worldmodel->brush.entities);
3993 R_Main_FreeViewCache();
3995 R_FrameData_Reset();
3998 void GL_Main_Init(void)
4000 r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4002 Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4003 Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4004 // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4005 if (gamemode == GAME_NEHAHRA)
4007 Cvar_RegisterVariable (&gl_fogenable);
4008 Cvar_RegisterVariable (&gl_fogdensity);
4009 Cvar_RegisterVariable (&gl_fogred);
4010 Cvar_RegisterVariable (&gl_foggreen);
4011 Cvar_RegisterVariable (&gl_fogblue);
4012 Cvar_RegisterVariable (&gl_fogstart);
4013 Cvar_RegisterVariable (&gl_fogend);
4014 Cvar_RegisterVariable (&gl_skyclip);
4016 Cvar_RegisterVariable(&r_motionblur);
4017 Cvar_RegisterVariable(&r_motionblur_maxblur);
4018 Cvar_RegisterVariable(&r_motionblur_bmin);
4019 Cvar_RegisterVariable(&r_motionblur_vmin);
4020 Cvar_RegisterVariable(&r_motionblur_vmax);
4021 Cvar_RegisterVariable(&r_motionblur_vcoeff);
4022 Cvar_RegisterVariable(&r_motionblur_randomize);
4023 Cvar_RegisterVariable(&r_damageblur);
4024 Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4025 Cvar_RegisterVariable(&r_equalize_entities_minambient);
4026 Cvar_RegisterVariable(&r_equalize_entities_by);
4027 Cvar_RegisterVariable(&r_equalize_entities_to);
4028 Cvar_RegisterVariable(&r_depthfirst);
4029 Cvar_RegisterVariable(&r_useinfinitefarclip);
4030 Cvar_RegisterVariable(&r_farclip_base);
4031 Cvar_RegisterVariable(&r_farclip_world);
4032 Cvar_RegisterVariable(&r_nearclip);
4033 Cvar_RegisterVariable(&r_showbboxes);
4034 Cvar_RegisterVariable(&r_showsurfaces);
4035 Cvar_RegisterVariable(&r_showtris);
4036 Cvar_RegisterVariable(&r_shownormals);
4037 Cvar_RegisterVariable(&r_showlighting);
4038 Cvar_RegisterVariable(&r_showshadowvolumes);
4039 Cvar_RegisterVariable(&r_showcollisionbrushes);
4040 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4041 Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4042 Cvar_RegisterVariable(&r_showdisabledepthtest);
4043 Cvar_RegisterVariable(&r_drawportals);
4044 Cvar_RegisterVariable(&r_drawentities);
4045 Cvar_RegisterVariable(&r_draw2d);
4046 Cvar_RegisterVariable(&r_drawworld);
4047 Cvar_RegisterVariable(&r_cullentities_trace);
4048 Cvar_RegisterVariable(&r_cullentities_trace_samples);
4049 Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4050 Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4051 Cvar_RegisterVariable(&r_cullentities_trace_delay);
4052 Cvar_RegisterVariable(&r_drawviewmodel);
4053 Cvar_RegisterVariable(&r_drawexteriormodel);
4054 Cvar_RegisterVariable(&r_speeds);
4055 Cvar_RegisterVariable(&r_fullbrights);
4056 Cvar_RegisterVariable(&r_wateralpha);
4057 Cvar_RegisterVariable(&r_dynamic);
4058 Cvar_RegisterVariable(&r_fakelight);
4059 Cvar_RegisterVariable(&r_fakelight_intensity);
4060 Cvar_RegisterVariable(&r_fullbright);
4061 Cvar_RegisterVariable(&r_shadows);
4062 Cvar_RegisterVariable(&r_shadows_darken);
4063 Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4064 Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4065 Cvar_RegisterVariable(&r_shadows_throwdistance);
4066 Cvar_RegisterVariable(&r_shadows_throwdirection);
4067 Cvar_RegisterVariable(&r_shadows_focus);
4068 Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4069 Cvar_RegisterVariable(&r_q1bsp_skymasking);
4070 Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4071 Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4072 Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4073 Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4074 Cvar_RegisterVariable(&r_fog_exp2);
4075 Cvar_RegisterVariable(&r_drawfog);
4076 Cvar_RegisterVariable(&r_transparentdepthmasking);
4077 Cvar_RegisterVariable(&r_texture_dds_load);
4078 Cvar_RegisterVariable(&r_texture_dds_save);
4079 Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
4080 Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
4081 Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
4082 Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
4083 Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
4084 Cvar_RegisterVariable(&r_textureunits);
4085 Cvar_RegisterVariable(&gl_combine);
4086 Cvar_RegisterVariable(&r_glsl);
4087 Cvar_RegisterVariable(&r_glsl_deluxemapping);
4088 Cvar_RegisterVariable(&r_glsl_offsetmapping);
4089 Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4090 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4091 Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4092 Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4093 Cvar_RegisterVariable(&r_glsl_postprocess);
4094 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4095 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4096 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4097 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4098 Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4099 Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4100 Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4101 Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4103 Cvar_RegisterVariable(&r_water);
4104 Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4105 Cvar_RegisterVariable(&r_water_clippingplanebias);
4106 Cvar_RegisterVariable(&r_water_refractdistort);
4107 Cvar_RegisterVariable(&r_water_reflectdistort);
4108 Cvar_RegisterVariable(&r_water_scissormode);
4109 Cvar_RegisterVariable(&r_lerpsprites);
4110 Cvar_RegisterVariable(&r_lerpmodels);
4111 Cvar_RegisterVariable(&r_lerplightstyles);
4112 Cvar_RegisterVariable(&r_waterscroll);
4113 Cvar_RegisterVariable(&r_bloom);
4114 Cvar_RegisterVariable(&r_bloom_colorscale);
4115 Cvar_RegisterVariable(&r_bloom_brighten);
4116 Cvar_RegisterVariable(&r_bloom_blur);
4117 Cvar_RegisterVariable(&r_bloom_resolution);
4118 Cvar_RegisterVariable(&r_bloom_colorexponent);
4119 Cvar_RegisterVariable(&r_bloom_colorsubtract);
4120 Cvar_RegisterVariable(&r_hdr);
4121 Cvar_RegisterVariable(&r_hdr_scenebrightness);
4122 Cvar_RegisterVariable(&r_hdr_glowintensity);
4123 Cvar_RegisterVariable(&r_hdr_range);
4124 Cvar_RegisterVariable(&r_hdr_irisadaptation);
4125 Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4126 Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4127 Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4128 Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4129 Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4130 Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4131 Cvar_RegisterVariable(&developer_texturelogging);
4132 Cvar_RegisterVariable(&gl_lightmaps);
4133 Cvar_RegisterVariable(&r_test);
4134 Cvar_RegisterVariable(&r_glsl_saturation);
4135 Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4136 Cvar_RegisterVariable(&r_framedatasize);
4137 if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4138 Cvar_SetValue("r_fullbrights", 0);
4139 R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4141 Cvar_RegisterVariable(&r_track_sprites);
4142 Cvar_RegisterVariable(&r_track_sprites_flags);
4143 Cvar_RegisterVariable(&r_track_sprites_scalew);
4144 Cvar_RegisterVariable(&r_track_sprites_scaleh);
4145 Cvar_RegisterVariable(&r_overheadsprites_perspective);
4146 Cvar_RegisterVariable(&r_overheadsprites_pushback);
4147 Cvar_RegisterVariable(&r_overheadsprites_scalex);
4148 Cvar_RegisterVariable(&r_overheadsprites_scaley);
4151 extern void R_Textures_Init(void);
4152 extern void GL_Draw_Init(void);
4153 extern void GL_Main_Init(void);
4154 extern void R_Shadow_Init(void);
4155 extern void R_Sky_Init(void);
4156 extern void GL_Surf_Init(void);
4157 extern void R_Particles_Init(void);
4158 extern void R_Explosion_Init(void);
4159 extern void gl_backend_init(void);
4160 extern void Sbar_Init(void);
4161 extern void R_LightningBeams_Init(void);
4162 extern void Mod_RenderInit(void);
4163 extern void Font_Init(void);
4165 void Render_Init(void)
4178 R_LightningBeams_Init();
4187 extern char *ENGINE_EXTENSIONS;
4190 gl_renderer = (const char *)qglGetString(GL_RENDERER);
4191 gl_vendor = (const char *)qglGetString(GL_VENDOR);
4192 gl_version = (const char *)qglGetString(GL_VERSION);
4193 gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4197 if (!gl_platformextensions)
4198 gl_platformextensions = "";
4200 Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4201 Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4202 Con_Printf("GL_VERSION: %s\n", gl_version);
4203 Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4204 Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4206 VID_CheckExtensions();
4208 // LordHavoc: report supported extensions
4209 Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4211 // clear to black (loading plaque will be seen over this)
4212 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4215 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4219 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4221 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4224 p = r_refdef.view.frustum + i;
4229 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4233 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4237 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4241 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4245 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4249 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4253 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4257 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4265 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4269 for (i = 0;i < numplanes;i++)
4276 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4280 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4284 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4288 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4292 if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4296 if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4300 if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4304 if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4312 //==================================================================================
4314 // LordHavoc: this stores temporary data used within the same frame
4316 typedef struct r_framedata_mem_s
4318 struct r_framedata_mem_s *purge; // older mem block to free on next frame
4319 size_t size; // how much usable space
4320 size_t current; // how much space in use
4321 size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4322 size_t wantedsize; // how much space was allocated
4323 unsigned char *data; // start of real data (16byte aligned)
4327 static r_framedata_mem_t *r_framedata_mem;
4329 void R_FrameData_Reset(void)
4331 while (r_framedata_mem)
4333 r_framedata_mem_t *next = r_framedata_mem->purge;
4334 Mem_Free(r_framedata_mem);
4335 r_framedata_mem = next;
4339 void R_FrameData_Resize(void)
4342 wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4343 wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4344 if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4346 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4347 newmem->wantedsize = wantedsize;
4348 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4349 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4350 newmem->current = 0;
4352 newmem->purge = r_framedata_mem;
4353 r_framedata_mem = newmem;
4357 void R_FrameData_NewFrame(void)
4359 R_FrameData_Resize();
4360 if (!r_framedata_mem)
4362 // if we ran out of space on the last frame, free the old memory now
4363 while (r_framedata_mem->purge)
4365 // repeatedly remove the second item in the list, leaving only head
4366 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4367 Mem_Free(r_framedata_mem->purge);
4368 r_framedata_mem->purge = next;
4370 // reset the current mem pointer
4371 r_framedata_mem->current = 0;
4372 r_framedata_mem->mark = 0;
4375 void *R_FrameData_Alloc(size_t size)
4379 // align to 16 byte boundary - the data pointer is already aligned, so we
4380 // only need to ensure the size of every allocation is also aligned
4381 size = (size + 15) & ~15;
4383 while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4385 // emergency - we ran out of space, allocate more memory
4386 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4387 R_FrameData_Resize();
4390 data = r_framedata_mem->data + r_framedata_mem->current;
4391 r_framedata_mem->current += size;
4393 // count the usage for stats
4394 r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4395 r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4397 return (void *)data;
4400 void *R_FrameData_Store(size_t size, void *data)
4402 void *d = R_FrameData_Alloc(size);
4404 memcpy(d, data, size);
4408 void R_FrameData_SetMark(void)
4410 if (!r_framedata_mem)
4412 r_framedata_mem->mark = r_framedata_mem->current;
4415 void R_FrameData_ReturnToMark(void)
4417 if (!r_framedata_mem)
4419 r_framedata_mem->current = r_framedata_mem->mark;
4422 //==================================================================================
4424 // LordHavoc: animcache originally written by Echon, rewritten since then
4427 * Animation cache prevents re-generating mesh data for an animated model
4428 * multiple times in one frame for lighting, shadowing, reflections, etc.
4431 void R_AnimCache_Free(void)
4435 void R_AnimCache_ClearCache(void)
4438 entity_render_t *ent;
4440 for (i = 0;i < r_refdef.scene.numentities;i++)
4442 ent = r_refdef.scene.entities[i];
4443 ent->animcache_vertex3f = NULL;
4444 ent->animcache_normal3f = NULL;
4445 ent->animcache_svector3f = NULL;
4446 ent->animcache_tvector3f = NULL;
4447 ent->animcache_vertexmesh = NULL;
4448 ent->animcache_vertex3fbuffer = NULL;
4449 ent->animcache_vertexmeshbuffer = NULL;
4453 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4457 // check if we need the meshbuffers
4458 if (!vid.useinterleavedarrays)
4461 if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4462 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4463 // TODO: upload vertex3f buffer?
4464 if (ent->animcache_vertexmesh)
4466 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4467 for (i = 0;i < numvertices;i++)
4468 memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4469 if (ent->animcache_svector3f)
4470 for (i = 0;i < numvertices;i++)
4471 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4472 if (ent->animcache_tvector3f)
4473 for (i = 0;i < numvertices;i++)
4474 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4475 if (ent->animcache_normal3f)
4476 for (i = 0;i < numvertices;i++)
4477 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4478 // TODO: upload vertexmeshbuffer?
4482 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4484 dp_model_t *model = ent->model;
4486 // see if it's already cached this frame
4487 if (ent->animcache_vertex3f)
4489 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4490 if (wantnormals || wanttangents)
4492 if (ent->animcache_normal3f)
4493 wantnormals = false;
4494 if (ent->animcache_svector3f)
4495 wanttangents = false;
4496 if (wantnormals || wanttangents)
4498 numvertices = model->surfmesh.num_vertices;
4500 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4503 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4504 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4506 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4507 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4513 // see if this ent is worth caching
4514 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
4516 // get some memory for this entity and generate mesh data
4517 numvertices = model->surfmesh.num_vertices;
4518 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4520 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4523 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4524 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4526 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4527 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4532 void R_AnimCache_CacheVisibleEntities(void)
4535 qboolean wantnormals = true;
4536 qboolean wanttangents = !r_showsurfaces.integer;
4538 switch(vid.renderpath)
4540 case RENDERPATH_GL20:
4541 case RENDERPATH_D3D9:
4542 case RENDERPATH_D3D10:
4543 case RENDERPATH_D3D11:
4544 case RENDERPATH_GLES2:
4546 case RENDERPATH_GL13:
4547 case RENDERPATH_GL11:
4548 wanttangents = false;
4550 case RENDERPATH_SOFT:
4554 if (r_shownormals.integer)
4555 wanttangents = wantnormals = true;
4557 // TODO: thread this
4558 // NOTE: R_PrepareRTLights() also caches entities
4560 for (i = 0;i < r_refdef.scene.numentities;i++)
4561 if (r_refdef.viewcache.entityvisible[i])
4562 R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4565 //==================================================================================
4567 static void R_View_UpdateEntityLighting (void)
4570 entity_render_t *ent;
4571 vec3_t tempdiffusenormal, avg;
4572 vec_t f, fa, fd, fdd;
4573 qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4575 for (i = 0;i < r_refdef.scene.numentities;i++)
4577 ent = r_refdef.scene.entities[i];
4579 // skip unseen models
4580 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4584 if (ent->model && ent->model->brush.num_leafs)
4586 // TODO: use modellight for r_ambient settings on world?
4587 VectorSet(ent->modellight_ambient, 0, 0, 0);
4588 VectorSet(ent->modellight_diffuse, 0, 0, 0);
4589 VectorSet(ent->modellight_lightdir, 0, 0, 1);
4593 // fetch the lighting from the worldmodel data
4594 VectorClear(ent->modellight_ambient);
4595 VectorClear(ent->modellight_diffuse);
4596 VectorClear(tempdiffusenormal);
4597 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
4600 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4602 // complete lightning for lit sprites
4603 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4604 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4606 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4607 org[2] = org[2] + r_overheadsprites_pushback.value;
4608 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4611 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4613 if(ent->flags & RENDER_EQUALIZE)
4615 // first fix up ambient lighting...
4616 if(r_equalize_entities_minambient.value > 0)
4618 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4621 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4622 if(fa < r_equalize_entities_minambient.value * fd)
4625 // fa'/fd' = minambient
4626 // fa'+0.25*fd' = fa+0.25*fd
4628 // fa' = fd' * minambient
4629 // fd'*(0.25+minambient) = fa+0.25*fd
4631 // fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4632 // fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4634 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4635 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
4636 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4637 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4642 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4644 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4645 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4649 // adjust brightness and saturation to target
4650 avg[0] = avg[1] = avg[2] = fa / f;
4651 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4652 avg[0] = avg[1] = avg[2] = fd / f;
4653 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4659 VectorSet(ent->modellight_ambient, 1, 1, 1);
4661 // move the light direction into modelspace coordinates for lighting code
4662 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4663 if(VectorLength2(ent->modellight_lightdir) == 0)
4664 VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4665 VectorNormalize(ent->modellight_lightdir);
4669 #define MAX_LINEOFSIGHTTRACES 64
4671 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4674 vec3_t boxmins, boxmaxs;
4677 dp_model_t *model = r_refdef.scene.worldmodel;
4679 if (!model || !model->brush.TraceLineOfSight)
4682 // expand the box a little
4683 boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4684 boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4685 boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4686 boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4687 boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4688 boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4690 // return true if eye is inside enlarged box
4691 if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4695 VectorCopy(eye, start);
4696 VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4697 if (model->brush.TraceLineOfSight(model, start, end))
4700 // try various random positions
4701 for (i = 0;i < numsamples;i++)
4703 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4704 if (model->brush.TraceLineOfSight(model, start, end))
4712 static void R_View_UpdateEntityVisible (void)
4717 entity_render_t *ent;
4719 renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4720 : r_waterstate.renderingrefraction ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4721 : (chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL
4722 : RENDER_EXTERIORMODEL;
4723 if (!r_drawviewmodel.integer)
4724 renderimask |= RENDER_VIEWMODEL;
4725 if (!r_drawexteriormodel.integer)
4726 renderimask |= RENDER_EXTERIORMODEL;
4727 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4729 // worldmodel can check visibility
4730 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4731 for (i = 0;i < r_refdef.scene.numentities;i++)
4733 ent = r_refdef.scene.entities[i];
4734 if (!(ent->flags & renderimask))
4735 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)))
4736 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))
4737 r_refdef.viewcache.entityvisible[i] = true;
4739 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
4740 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4742 for (i = 0;i < r_refdef.scene.numentities;i++)
4744 ent = r_refdef.scene.entities[i];
4745 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4747 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4749 continue; // temp entities do pvs only
4750 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4751 ent->last_trace_visibility = realtime;
4752 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4753 r_refdef.viewcache.entityvisible[i] = 0;
4760 // no worldmodel or it can't check visibility
4761 for (i = 0;i < r_refdef.scene.numentities;i++)
4763 ent = r_refdef.scene.entities[i];
4764 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));
4769 /// only used if skyrendermasked, and normally returns false
4770 int R_DrawBrushModelsSky (void)
4773 entity_render_t *ent;
4776 for (i = 0;i < r_refdef.scene.numentities;i++)
4778 if (!r_refdef.viewcache.entityvisible[i])
4780 ent = r_refdef.scene.entities[i];
4781 if (!ent->model || !ent->model->DrawSky)
4783 ent->model->DrawSky(ent);
4789 static void R_DrawNoModel(entity_render_t *ent);
4790 static void R_DrawModels(void)
4793 entity_render_t *ent;
4795 for (i = 0;i < r_refdef.scene.numentities;i++)
4797 if (!r_refdef.viewcache.entityvisible[i])
4799 ent = r_refdef.scene.entities[i];
4800 r_refdef.stats.entities++;
4801 if (ent->model && ent->model->Draw != NULL)
4802 ent->model->Draw(ent);
4808 static void R_DrawModelsDepth(void)
4811 entity_render_t *ent;
4813 for (i = 0;i < r_refdef.scene.numentities;i++)
4815 if (!r_refdef.viewcache.entityvisible[i])
4817 ent = r_refdef.scene.entities[i];
4818 if (ent->model && ent->model->DrawDepth != NULL)
4819 ent->model->DrawDepth(ent);
4823 static void R_DrawModelsDebug(void)
4826 entity_render_t *ent;
4828 for (i = 0;i < r_refdef.scene.numentities;i++)
4830 if (!r_refdef.viewcache.entityvisible[i])
4832 ent = r_refdef.scene.entities[i];
4833 if (ent->model && ent->model->DrawDebug != NULL)
4834 ent->model->DrawDebug(ent);
4838 static void R_DrawModelsAddWaterPlanes(void)
4841 entity_render_t *ent;
4843 for (i = 0;i < r_refdef.scene.numentities;i++)
4845 if (!r_refdef.viewcache.entityvisible[i])
4847 ent = r_refdef.scene.entities[i];
4848 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4849 ent->model->DrawAddWaterPlanes(ent);
4853 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
4855 if (r_hdr_irisadaptation.integer)
4859 vec3_t diffusenormal;
4864 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4865 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
4866 brightness = max(0.0000001f, brightness);
4867 goal = r_hdr_irisadaptation_multiplier.value / brightness;
4868 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
4869 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
4870 current = r_hdr_irisadaptation_value.value;
4872 current = min(current + adjust, goal);
4873 else if (current > goal)
4874 current = max(current - adjust, goal);
4875 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
4876 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
4878 else if (r_hdr_irisadaptation_value.value != 1.0f)
4879 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
4882 static void R_View_SetFrustum(const int *scissor)
4885 double fpx = +1, fnx = -1, fpy = +1, fny = -1;
4886 vec3_t forward, left, up, origin, v;
4890 // flipped x coordinates (because x points left here)
4891 fpx = 1.0 - 2.0 * (scissor[0] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4892 fnx = 1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
4894 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
4895 switch(vid.renderpath)
4897 case RENDERPATH_D3D9:
4898 case RENDERPATH_D3D10:
4899 case RENDERPATH_D3D11:
4900 case RENDERPATH_SOFT:
4901 // non-flipped y coordinates
4902 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4903 fpy = -1.0 + 2.0 * (vid.height - scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4905 case RENDERPATH_GL11:
4906 case RENDERPATH_GL13:
4907 case RENDERPATH_GL20:
4908 case RENDERPATH_GLES2:
4909 // non-flipped y coordinates
4910 fny = -1.0 + 2.0 * (scissor[1] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4911 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
4916 // we can't trust r_refdef.view.forward and friends in reflected scenes
4917 Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
4920 r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
4921 r_refdef.view.frustum[0].normal[1] = 0 - 0;
4922 r_refdef.view.frustum[0].normal[2] = -1 - 0;
4923 r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
4924 r_refdef.view.frustum[1].normal[1] = 0 + 0;
4925 r_refdef.view.frustum[1].normal[2] = -1 + 0;
4926 r_refdef.view.frustum[2].normal[0] = 0 - 0;
4927 r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
4928 r_refdef.view.frustum[2].normal[2] = -1 - 0;
4929 r_refdef.view.frustum[3].normal[0] = 0 + 0;
4930 r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
4931 r_refdef.view.frustum[3].normal[2] = -1 + 0;
4935 zNear = r_refdef.nearclip;
4936 nudge = 1.0 - 1.0 / (1<<23);
4937 r_refdef.view.frustum[4].normal[0] = 0 - 0;
4938 r_refdef.view.frustum[4].normal[1] = 0 - 0;
4939 r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
4940 r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
4941 r_refdef.view.frustum[5].normal[0] = 0 + 0;
4942 r_refdef.view.frustum[5].normal[1] = 0 + 0;
4943 r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
4944 r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
4950 r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
4951 r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
4952 r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
4953 r_refdef.view.frustum[0].dist = m[15] - m[12];
4955 r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
4956 r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
4957 r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
4958 r_refdef.view.frustum[1].dist = m[15] + m[12];
4960 r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
4961 r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
4962 r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
4963 r_refdef.view.frustum[2].dist = m[15] - m[13];
4965 r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
4966 r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
4967 r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
4968 r_refdef.view.frustum[3].dist = m[15] + m[13];
4970 r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
4971 r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
4972 r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
4973 r_refdef.view.frustum[4].dist = m[15] - m[14];
4975 r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
4976 r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
4977 r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
4978 r_refdef.view.frustum[5].dist = m[15] + m[14];
4981 if (r_refdef.view.useperspective)
4983 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
4984 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]);
4985 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]);
4986 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]);
4987 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]);
4989 // then the normals from the corners relative to origin
4990 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
4991 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
4992 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
4993 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
4995 // in a NORMAL view, forward cross left == up
4996 // in a REFLECTED view, forward cross left == down
4997 // so our cross products above need to be adjusted for a left handed coordinate system
4998 CrossProduct(forward, left, v);
4999 if(DotProduct(v, up) < 0)
5001 VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5002 VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5003 VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5004 VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5007 // Leaving those out was a mistake, those were in the old code, and they
5008 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5009 // I couldn't reproduce it after adding those normalizations. --blub
5010 VectorNormalize(r_refdef.view.frustum[0].normal);
5011 VectorNormalize(r_refdef.view.frustum[1].normal);
5012 VectorNormalize(r_refdef.view.frustum[2].normal);
5013 VectorNormalize(r_refdef.view.frustum[3].normal);
5015 // make the corners absolute
5016 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5017 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5018 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5019 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5022 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5024 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5025 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5026 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5027 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5028 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5032 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5033 VectorScale(left, r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5034 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5035 VectorScale(up, r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5036 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5037 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5038 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5039 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5040 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5041 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5043 r_refdef.view.numfrustumplanes = 5;
5045 if (r_refdef.view.useclipplane)
5047 r_refdef.view.numfrustumplanes = 6;
5048 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5051 for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5052 PlaneClassify(r_refdef.view.frustum + i);
5054 // LordHavoc: note to all quake engine coders, Quake had a special case
5055 // for 90 degrees which assumed a square view (wrong), so I removed it,
5056 // Quake2 has it disabled as well.
5058 // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5059 //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5060 //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5061 //PlaneClassify(&frustum[0]);
5063 // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5064 //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5065 //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5066 //PlaneClassify(&frustum[1]);
5068 // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5069 //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5070 //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5071 //PlaneClassify(&frustum[2]);
5073 // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5074 //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5075 //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5076 //PlaneClassify(&frustum[3]);
5079 //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5080 //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5081 //PlaneClassify(&frustum[4]);
5084 void R_View_UpdateWithScissor(const int *myscissor)
5086 R_Main_ResizeViewCache();
5087 R_View_SetFrustum(myscissor);
5088 R_View_WorldVisibility(r_refdef.view.useclipplane);
5089 R_View_UpdateEntityVisible();
5090 R_View_UpdateEntityLighting();
5093 void R_View_Update(void)
5095 R_Main_ResizeViewCache();
5096 R_View_SetFrustum(NULL);
5097 R_View_WorldVisibility(r_refdef.view.useclipplane);
5098 R_View_UpdateEntityVisible();
5099 R_View_UpdateEntityLighting();
5102 void R_SetupView(qboolean allowwaterclippingplane)
5104 const float *customclipplane = NULL;
5106 if (r_refdef.view.useclipplane && allowwaterclippingplane)
5108 // LordHavoc: couldn't figure out how to make this approach the
5109 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5110 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5111 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5112 dist = r_refdef.view.clipplane.dist;
5113 plane[0] = r_refdef.view.clipplane.normal[0];
5114 plane[1] = r_refdef.view.clipplane.normal[1];
5115 plane[2] = r_refdef.view.clipplane.normal[2];
5117 customclipplane = plane;
5120 if (!r_refdef.view.useperspective)
5121 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);
5122 else if (vid.stencil && r_useinfinitefarclip.integer)
5123 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);
5125 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);
5126 R_SetViewport(&r_refdef.view.viewport);
5129 void R_EntityMatrix(const matrix4x4_t *matrix)
5131 if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5133 gl_modelmatrixchanged = false;
5134 gl_modelmatrix = *matrix;
5135 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5136 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5137 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5138 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5140 switch(vid.renderpath)
5142 case RENDERPATH_D3D9:
5144 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5145 hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5148 case RENDERPATH_D3D10:
5149 Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5151 case RENDERPATH_D3D11:
5152 Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5154 case RENDERPATH_GL13:
5155 case RENDERPATH_GL11:
5156 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5158 case RENDERPATH_SOFT:
5159 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5160 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5162 case RENDERPATH_GL20:
5163 case RENDERPATH_GLES2:
5164 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5165 if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5171 void R_ResetViewRendering2D(void)
5173 r_viewport_t viewport;
5176 // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5177 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);
5178 R_SetViewport(&viewport);
5179 GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5180 GL_Color(1, 1, 1, 1);
5181 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5182 GL_BlendFunc(GL_ONE, GL_ZERO);
5183 GL_ScissorTest(false);
5184 GL_DepthMask(false);
5185 GL_DepthRange(0, 1);
5186 GL_DepthTest(false);
5187 GL_DepthFunc(GL_LEQUAL);
5188 R_EntityMatrix(&identitymatrix);
5189 R_Mesh_ResetTextureState();
5190 GL_PolygonOffset(0, 0);
5191 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5192 switch(vid.renderpath)
5194 case RENDERPATH_GL11:
5195 case RENDERPATH_GL13:
5196 case RENDERPATH_GL20:
5197 case RENDERPATH_GLES2:
5198 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5200 case RENDERPATH_D3D9:
5201 case RENDERPATH_D3D10:
5202 case RENDERPATH_D3D11:
5203 case RENDERPATH_SOFT:
5206 GL_CullFace(GL_NONE);
5209 void R_ResetViewRendering3D(void)
5214 GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5215 GL_Color(1, 1, 1, 1);
5216 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5217 GL_BlendFunc(GL_ONE, GL_ZERO);
5218 GL_ScissorTest(true);
5220 GL_DepthRange(0, 1);
5222 GL_DepthFunc(GL_LEQUAL);
5223 R_EntityMatrix(&identitymatrix);
5224 R_Mesh_ResetTextureState();
5225 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5226 R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5227 switch(vid.renderpath)
5229 case RENDERPATH_GL11:
5230 case RENDERPATH_GL13:
5231 case RENDERPATH_GL20:
5232 case RENDERPATH_GLES2:
5233 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5235 case RENDERPATH_D3D9:
5236 case RENDERPATH_D3D10:
5237 case RENDERPATH_D3D11:
5238 case RENDERPATH_SOFT:
5241 GL_CullFace(r_refdef.view.cullface_back);
5246 R_RenderView_UpdateViewVectors
5249 static void R_RenderView_UpdateViewVectors(void)
5251 // break apart the view matrix into vectors for various purposes
5252 // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5253 // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5254 Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5255 VectorNegate(r_refdef.view.left, r_refdef.view.right);
5256 // make an inverted copy of the view matrix for tracking sprites
5257 Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5260 void R_RenderScene(void);
5261 void R_RenderWaterPlanes(void);
5263 static void R_Water_StartFrame(void)
5266 int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5267 r_waterstate_waterplane_t *p;
5269 if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5272 switch(vid.renderpath)
5274 case RENDERPATH_GL20:
5275 case RENDERPATH_D3D9:
5276 case RENDERPATH_D3D10:
5277 case RENDERPATH_D3D11:
5278 case RENDERPATH_SOFT:
5279 case RENDERPATH_GLES2:
5281 case RENDERPATH_GL13:
5282 case RENDERPATH_GL11:
5286 // set waterwidth and waterheight to the water resolution that will be
5287 // used (often less than the screen resolution for faster rendering)
5288 waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
5289 waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
5291 // calculate desired texture sizes
5292 // can't use water if the card does not support the texture size
5293 if (!r_water.integer || r_showsurfaces.integer)
5294 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5295 else if (vid.support.arb_texture_non_power_of_two)
5297 texturewidth = waterwidth;
5298 textureheight = waterheight;
5299 camerawidth = waterwidth;
5300 cameraheight = waterheight;
5304 for (texturewidth = 1;texturewidth < waterwidth ;texturewidth *= 2);
5305 for (textureheight = 1;textureheight < waterheight;textureheight *= 2);
5306 for (camerawidth = 1;camerawidth <= waterwidth; camerawidth *= 2); camerawidth /= 2;
5307 for (cameraheight = 1;cameraheight <= waterheight;cameraheight *= 2); cameraheight /= 2;
5310 // allocate textures as needed
5311 if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5313 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5314 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5316 if (p->texture_refraction)
5317 R_FreeTexture(p->texture_refraction);
5318 p->texture_refraction = NULL;
5319 if (p->texture_reflection)
5320 R_FreeTexture(p->texture_reflection);
5321 p->texture_reflection = NULL;
5322 if (p->texture_camera)
5323 R_FreeTexture(p->texture_camera);
5324 p->texture_camera = NULL;
5326 memset(&r_waterstate, 0, sizeof(r_waterstate));
5327 r_waterstate.texturewidth = texturewidth;
5328 r_waterstate.textureheight = textureheight;
5329 r_waterstate.camerawidth = camerawidth;
5330 r_waterstate.cameraheight = cameraheight;
5333 if (r_waterstate.texturewidth)
5335 r_waterstate.enabled = true;
5337 // when doing a reduced render (HDR) we want to use a smaller area
5338 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5339 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5341 // set up variables that will be used in shader setup
5342 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5343 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5344 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
5345 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
5348 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5349 r_waterstate.numwaterplanes = 0;
5352 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5354 int triangleindex, planeindex;
5360 r_waterstate_waterplane_t *p;
5361 texture_t *t = R_GetCurrentTexture(surface->texture);
5363 // just use the first triangle with a valid normal for any decisions
5364 VectorClear(normal);
5365 for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5367 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5368 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5369 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5370 TriangleNormal(vert[0], vert[1], vert[2], normal);
5371 if (VectorLength2(normal) >= 0.001)
5375 VectorCopy(normal, plane.normal);
5376 VectorNormalize(plane.normal);
5377 plane.dist = DotProduct(vert[0], plane.normal);
5378 PlaneClassify(&plane);
5379 if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5381 // skip backfaces (except if nocullface is set)
5382 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5384 VectorNegate(plane.normal, plane.normal);
5386 PlaneClassify(&plane);
5390 // find a matching plane if there is one
5391 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5392 if(p->camera_entity == t->camera_entity)
5393 if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5395 if (planeindex >= r_waterstate.maxwaterplanes)
5396 return; // nothing we can do, out of planes
5398 // if this triangle does not fit any known plane rendered this frame, add one
5399 if (planeindex >= r_waterstate.numwaterplanes)
5401 // store the new plane
5402 r_waterstate.numwaterplanes++;
5404 // clear materialflags and pvs
5405 p->materialflags = 0;
5406 p->pvsvalid = false;
5407 p->camera_entity = t->camera_entity;
5408 VectorCopy(surface->mins, p->mins);
5409 VectorCopy(surface->maxs, p->maxs);
5414 p->mins[0] = min(p->mins[0], surface->mins[0]);
5415 p->mins[1] = min(p->mins[1], surface->mins[1]);
5416 p->mins[2] = min(p->mins[2], surface->mins[2]);
5417 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5418 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5419 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5421 // merge this surface's materialflags into the waterplane
5422 p->materialflags |= t->currentmaterialflags;
5423 if(!(p->materialflags & MATERIALFLAG_CAMERA))
5425 // merge this surface's PVS into the waterplane
5426 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5427 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5428 && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5430 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5436 static void R_Water_ProcessPlanes(void)
5439 r_refdef_view_t originalview;
5440 r_refdef_view_t myview;
5442 r_waterstate_waterplane_t *p;
5445 originalview = r_refdef.view;
5447 // make sure enough textures are allocated
5448 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5450 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5452 if (!p->texture_refraction)
5453 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);
5454 if (!p->texture_refraction)
5457 else if (p->materialflags & MATERIALFLAG_CAMERA)
5459 if (!p->texture_camera)
5460 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);
5461 if (!p->texture_camera)
5465 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5467 if (!p->texture_reflection)
5468 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);
5469 if (!p->texture_reflection)
5475 r_refdef.view = originalview;
5476 r_refdef.view.showdebug = false;
5477 r_refdef.view.width = r_waterstate.waterwidth;
5478 r_refdef.view.height = r_waterstate.waterheight;
5479 r_refdef.view.useclipplane = true;
5480 myview = r_refdef.view;
5481 r_waterstate.renderingscene = true;
5482 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5484 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5486 r_refdef.view = myview;
5487 if(r_water_scissormode.integer)
5490 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5491 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5494 // render reflected scene and copy into texture
5495 Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5496 // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5497 Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5498 r_refdef.view.clipplane = p->plane;
5500 // reverse the cullface settings for this render
5501 r_refdef.view.cullface_front = GL_FRONT;
5502 r_refdef.view.cullface_back = GL_BACK;
5503 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5505 r_refdef.view.usecustompvs = true;
5507 memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5509 memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5512 R_ResetViewRendering3D();
5513 R_ClearScreen(r_refdef.fogenabled);
5514 if(r_water_scissormode.integer & 2)
5515 R_View_UpdateWithScissor(myscissor);
5518 if(r_water_scissormode.integer & 1)
5519 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5522 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);
5525 // render the normal view scene and copy into texture
5526 // (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)
5527 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5529 r_refdef.view = myview;
5530 if(r_water_scissormode.integer)
5533 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5534 continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5537 r_waterstate.renderingrefraction = true;
5539 r_refdef.view.clipplane = p->plane;
5540 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5541 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5543 if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5545 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5546 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5547 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5548 R_RenderView_UpdateViewVectors();
5549 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5551 r_refdef.view.usecustompvs = true;
5552 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);
5556 PlaneClassify(&r_refdef.view.clipplane);
5558 R_ResetViewRendering3D();
5559 R_ClearScreen(r_refdef.fogenabled);
5560 if(r_water_scissormode.integer & 2)
5561 R_View_UpdateWithScissor(myscissor);
5564 if(r_water_scissormode.integer & 1)
5565 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5568 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);
5569 r_waterstate.renderingrefraction = false;
5571 else if (p->materialflags & MATERIALFLAG_CAMERA)
5573 r_refdef.view = myview;
5575 r_refdef.view.clipplane = p->plane;
5576 VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5577 r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5579 r_refdef.view.width = r_waterstate.camerawidth;
5580 r_refdef.view.height = r_waterstate.cameraheight;
5581 r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5582 r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5584 if(p->camera_entity)
5586 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5587 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5590 // note: all of the view is used for displaying... so
5591 // there is no use in scissoring
5593 // reverse the cullface settings for this render
5594 r_refdef.view.cullface_front = GL_FRONT;
5595 r_refdef.view.cullface_back = GL_BACK;
5596 // also reverse the view matrix
5597 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
5598 R_RenderView_UpdateViewVectors();
5599 if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5601 r_refdef.view.usecustompvs = true;
5602 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);
5605 // camera needs no clipplane
5606 r_refdef.view.useclipplane = false;
5608 PlaneClassify(&r_refdef.view.clipplane);
5610 R_ResetViewRendering3D();
5611 R_ClearScreen(r_refdef.fogenabled);
5615 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);
5616 r_waterstate.renderingrefraction = false;
5620 r_waterstate.renderingscene = false;
5621 r_refdef.view = originalview;
5622 R_ResetViewRendering3D();
5623 R_ClearScreen(r_refdef.fogenabled);
5627 r_refdef.view = originalview;
5628 r_waterstate.renderingscene = false;
5629 Cvar_SetValueQuick(&r_water, 0);
5630 Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
5634 void R_Bloom_StartFrame(void)
5636 int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5638 switch(vid.renderpath)
5640 case RENDERPATH_GL20:
5641 case RENDERPATH_D3D9:
5642 case RENDERPATH_D3D10:
5643 case RENDERPATH_D3D11:
5644 case RENDERPATH_SOFT:
5645 case RENDERPATH_GLES2:
5647 case RENDERPATH_GL13:
5648 case RENDERPATH_GL11:
5652 // set bloomwidth and bloomheight to the bloom resolution that will be
5653 // used (often less than the screen resolution for faster rendering)
5654 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5655 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5656 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5657 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5658 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5660 // calculate desired texture sizes
5661 if (vid.support.arb_texture_non_power_of_two)
5663 screentexturewidth = r_refdef.view.width;
5664 screentextureheight = r_refdef.view.height;
5665 bloomtexturewidth = r_bloomstate.bloomwidth;
5666 bloomtextureheight = r_bloomstate.bloomheight;
5670 for (screentexturewidth = 1;screentexturewidth < vid.width ;screentexturewidth *= 2);
5671 for (screentextureheight = 1;screentextureheight < vid.height ;screentextureheight *= 2);
5672 for (bloomtexturewidth = 1;bloomtexturewidth < r_bloomstate.bloomwidth ;bloomtexturewidth *= 2);
5673 for (bloomtextureheight = 1;bloomtextureheight < r_bloomstate.bloomheight;bloomtextureheight *= 2);
5676 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))
5678 Cvar_SetValueQuick(&r_hdr, 0);
5679 Cvar_SetValueQuick(&r_bloom, 0);
5680 Cvar_SetValueQuick(&r_motionblur, 0);
5681 Cvar_SetValueQuick(&r_damageblur, 0);
5684 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)))
5685 screentexturewidth = screentextureheight = 0;
5686 if (!r_hdr.integer && !r_bloom.integer)
5687 bloomtexturewidth = bloomtextureheight = 0;
5689 // allocate textures as needed
5690 if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
5692 if (r_bloomstate.texture_screen)
5693 R_FreeTexture(r_bloomstate.texture_screen);
5694 r_bloomstate.texture_screen = NULL;
5695 r_bloomstate.screentexturewidth = screentexturewidth;
5696 r_bloomstate.screentextureheight = screentextureheight;
5697 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5698 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);
5700 if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
5702 if (r_bloomstate.texture_bloom)
5703 R_FreeTexture(r_bloomstate.texture_bloom);
5704 r_bloomstate.texture_bloom = NULL;
5705 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
5706 r_bloomstate.bloomtextureheight = bloomtextureheight;
5707 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
5708 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);
5711 // when doing a reduced render (HDR) we want to use a smaller area
5712 r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
5713 r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
5714 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
5715 r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
5716 r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
5718 // set up a texcoord array for the full resolution screen image
5719 // (we have to keep this around to copy back during final render)
5720 r_bloomstate.screentexcoord2f[0] = 0;
5721 r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5722 r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5723 r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height / (float)r_bloomstate.screentextureheight;
5724 r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width / (float)r_bloomstate.screentexturewidth;
5725 r_bloomstate.screentexcoord2f[5] = 0;
5726 r_bloomstate.screentexcoord2f[6] = 0;
5727 r_bloomstate.screentexcoord2f[7] = 0;
5729 // set up a texcoord array for the reduced resolution bloom image
5730 // (which will be additive blended over the screen image)
5731 r_bloomstate.bloomtexcoord2f[0] = 0;
5732 r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5733 r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5734 r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5735 r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5736 r_bloomstate.bloomtexcoord2f[5] = 0;
5737 r_bloomstate.bloomtexcoord2f[6] = 0;
5738 r_bloomstate.bloomtexcoord2f[7] = 0;
5740 switch(vid.renderpath)
5742 case RENDERPATH_GL11:
5743 case RENDERPATH_GL13:
5744 case RENDERPATH_GL20:
5745 case RENDERPATH_SOFT:
5746 case RENDERPATH_GLES2:
5748 case RENDERPATH_D3D9:
5749 case RENDERPATH_D3D10:
5750 case RENDERPATH_D3D11:
5753 for (i = 0;i < 4;i++)
5755 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
5756 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
5757 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
5758 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
5764 if (r_hdr.integer || r_bloom.integer)
5766 r_bloomstate.enabled = true;
5767 r_bloomstate.hdr = r_hdr.integer != 0;
5770 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);
5773 void R_Bloom_CopyBloomTexture(float colorscale)
5775 r_refdef.stats.bloom++;
5777 // scale down screen texture to the bloom texture size
5779 R_SetViewport(&r_bloomstate.viewport);
5780 GL_BlendFunc(GL_ONE, GL_ZERO);
5781 GL_Color(colorscale, colorscale, colorscale, 1);
5782 // 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...
5783 switch(vid.renderpath)
5785 case RENDERPATH_GL11:
5786 case RENDERPATH_GL13:
5787 case RENDERPATH_GL20:
5788 case RENDERPATH_SOFT:
5789 case RENDERPATH_GLES2:
5790 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5792 case RENDERPATH_D3D9:
5793 case RENDERPATH_D3D10:
5794 case RENDERPATH_D3D11:
5795 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
5798 // TODO: do boxfilter scale-down in shader?
5799 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
5800 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5801 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5803 // we now have a bloom image in the framebuffer
5804 // copy it into the bloom image texture for later processing
5805 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);
5806 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5809 void R_Bloom_CopyHDRTexture(void)
5811 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);
5812 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
5815 void R_Bloom_MakeTexture(void)
5818 float xoffset, yoffset, r, brighten;
5820 r_refdef.stats.bloom++;
5822 R_ResetViewRendering2D();
5824 // we have a bloom image in the framebuffer
5826 R_SetViewport(&r_bloomstate.viewport);
5828 for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
5831 r = bound(0, r_bloom_colorexponent.value / x, 1);
5832 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
5834 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
5835 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5836 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5837 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5839 // copy the vertically blurred bloom view to a texture
5840 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);
5841 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5844 range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
5845 brighten = r_bloom_brighten.value;
5847 brighten *= r_hdr_range.value;
5848 brighten = sqrt(brighten);
5850 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
5851 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
5853 for (dir = 0;dir < 2;dir++)
5855 // blend on at multiple vertical offsets to achieve a vertical blur
5856 // TODO: do offset blends using GLSL
5857 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
5858 GL_BlendFunc(GL_ONE, GL_ZERO);
5859 for (x = -range;x <= range;x++)
5861 if (!dir){xoffset = 0;yoffset = x;}
5862 else {xoffset = x;yoffset = 0;}
5863 xoffset /= (float)r_bloomstate.bloomtexturewidth;
5864 yoffset /= (float)r_bloomstate.bloomtextureheight;
5865 // compute a texcoord array with the specified x and y offset
5866 r_bloomstate.offsettexcoord2f[0] = xoffset+0;
5867 r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5868 r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5869 r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
5870 r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
5871 r_bloomstate.offsettexcoord2f[5] = yoffset+0;
5872 r_bloomstate.offsettexcoord2f[6] = xoffset+0;
5873 r_bloomstate.offsettexcoord2f[7] = yoffset+0;
5874 // this r value looks like a 'dot' particle, fading sharply to
5875 // black at the edges
5876 // (probably not realistic but looks good enough)
5877 //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
5878 //r = brighten/(range*2+1);
5879 r = brighten / (range * 2 + 1);
5881 r *= (1 - x*x/(float)(range*range));
5882 GL_Color(r, r, r, 1);
5883 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
5884 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
5885 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
5886 GL_BlendFunc(GL_ONE, GL_ONE);
5889 // copy the vertically blurred bloom view to a texture
5890 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);
5891 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
5895 void R_HDR_RenderBloomTexture(void)
5897 int oldwidth, oldheight;
5898 float oldcolorscale;
5899 qboolean oldwaterstate;
5901 oldwaterstate = r_waterstate.enabled;
5902 oldcolorscale = r_refdef.view.colorscale;
5903 oldwidth = r_refdef.view.width;
5904 oldheight = r_refdef.view.height;
5905 r_refdef.view.width = r_bloomstate.bloomwidth;
5906 r_refdef.view.height = r_bloomstate.bloomheight;
5908 if(r_hdr.integer < 2)
5909 r_waterstate.enabled = false;
5911 // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
5912 // TODO: add exposure compensation features
5913 // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
5915 r_refdef.view.showdebug = false;
5916 r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
5918 R_ResetViewRendering3D();
5920 R_ClearScreen(r_refdef.fogenabled);
5921 if (r_timereport_active)
5922 R_TimeReport("HDRclear");
5925 if (r_timereport_active)
5926 R_TimeReport("visibility");
5928 // only do secondary renders with HDR if r_hdr is 2 or higher
5929 r_waterstate.numwaterplanes = 0;
5930 if (r_waterstate.enabled)
5931 R_RenderWaterPlanes();
5933 r_refdef.view.showdebug = true;
5935 r_waterstate.numwaterplanes = 0;
5937 R_ResetViewRendering2D();
5939 R_Bloom_CopyHDRTexture();
5940 R_Bloom_MakeTexture();
5942 // restore the view settings
5943 r_waterstate.enabled = oldwaterstate;
5944 r_refdef.view.width = oldwidth;
5945 r_refdef.view.height = oldheight;
5946 r_refdef.view.colorscale = oldcolorscale;
5948 R_ResetViewRendering3D();
5950 R_ClearScreen(r_refdef.fogenabled);
5951 if (r_timereport_active)
5952 R_TimeReport("viewclear");
5955 static void R_BlendView(void)
5957 unsigned int permutation;
5958 float uservecs[4][4];
5960 switch (vid.renderpath)
5962 case RENDERPATH_GL20:
5963 case RENDERPATH_D3D9:
5964 case RENDERPATH_D3D10:
5965 case RENDERPATH_D3D11:
5966 case RENDERPATH_SOFT:
5967 case RENDERPATH_GLES2:
5969 (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
5970 | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
5971 | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
5972 | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
5973 | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
5975 if (r_bloomstate.texture_screen)
5977 // make sure the buffer is available
5978 if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
5980 R_ResetViewRendering2D();
5982 if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
5984 // declare variables
5986 static float avgspeed;
5988 speed = VectorLength(cl.movement_velocity);
5990 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
5991 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
5993 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
5994 speed = bound(0, speed, 1);
5995 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
5997 // calculate values into a standard alpha
5998 cl.motionbluralpha = 1 - exp(-
6000 (r_motionblur.value * speed / 80)
6002 (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6005 max(0.0001, cl.time - cl.oldtime) // fps independent
6008 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6009 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6011 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6013 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6014 GL_Color(1, 1, 1, cl.motionbluralpha);
6015 switch(vid.renderpath)
6017 case RENDERPATH_GL11:
6018 case RENDERPATH_GL13:
6019 case RENDERPATH_GL20:
6020 case RENDERPATH_SOFT:
6021 case RENDERPATH_GLES2:
6022 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6024 case RENDERPATH_D3D9:
6025 case RENDERPATH_D3D10:
6026 case RENDERPATH_D3D11:
6027 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6030 R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
6031 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6032 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6036 // copy view into the screen texture
6037 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);
6038 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6040 else if (!r_bloomstate.texture_bloom)
6042 // we may still have to do view tint...
6043 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6045 // apply a color tint to the whole view
6046 R_ResetViewRendering2D();
6047 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6048 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6049 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6050 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6051 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6053 break; // no screen processing, no bloom, skip it
6056 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6058 // render simple bloom effect
6059 // copy the screen and shrink it and darken it for the bloom process
6060 R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6061 // make the bloom texture
6062 R_Bloom_MakeTexture();
6065 #if _MSC_VER >= 1400
6066 #define sscanf sscanf_s
6068 memset(uservecs, 0, sizeof(uservecs));
6069 if (r_glsl_postprocess_uservec1_enable.integer)
6070 sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6071 if (r_glsl_postprocess_uservec2_enable.integer)
6072 sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6073 if (r_glsl_postprocess_uservec3_enable.integer)
6074 sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6075 if (r_glsl_postprocess_uservec4_enable.integer)
6076 sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6078 R_ResetViewRendering2D();
6079 GL_Color(1, 1, 1, 1);
6080 GL_BlendFunc(GL_ONE, GL_ZERO);
6082 switch(vid.renderpath)
6084 case RENDERPATH_GL20:
6085 case RENDERPATH_GLES2:
6086 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6087 R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6088 if (r_glsl_permutation->tex_Texture_First >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , r_bloomstate.texture_screen);
6089 if (r_glsl_permutation->tex_Texture_Second >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second , r_bloomstate.texture_bloom );
6090 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps );
6091 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]);
6092 if (r_glsl_permutation->loc_PixelSize >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6093 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]);
6094 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]);
6095 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]);
6096 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]);
6097 if (r_glsl_permutation->loc_Saturation >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation , r_glsl_saturation.value);
6098 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6099 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);
6101 case RENDERPATH_D3D9:
6103 // 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...
6104 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6105 R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6106 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6107 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6108 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6109 hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6110 hlslPSSetParameter2f(D3DPSREGISTER_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6111 hlslPSSetParameter4f(D3DPSREGISTER_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6112 hlslPSSetParameter4f(D3DPSREGISTER_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6113 hlslPSSetParameter4f(D3DPSREGISTER_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6114 hlslPSSetParameter4f(D3DPSREGISTER_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6115 hlslPSSetParameter1f(D3DPSREGISTER_Saturation , r_glsl_saturation.value);
6116 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6117 hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6120 case RENDERPATH_D3D10:
6121 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6123 case RENDERPATH_D3D11:
6124 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6126 case RENDERPATH_SOFT:
6127 R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6128 R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6129 R_Mesh_TexBind(GL20TU_FIRST , r_bloomstate.texture_screen);
6130 R_Mesh_TexBind(GL20TU_SECOND , r_bloomstate.texture_bloom );
6131 R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps );
6132 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6133 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6134 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1 , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6135 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2 , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6136 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3 , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6137 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4 , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6138 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation , r_glsl_saturation.value);
6139 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6140 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6145 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6146 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6148 case RENDERPATH_GL13:
6149 case RENDERPATH_GL11:
6150 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6152 // apply a color tint to the whole view
6153 R_ResetViewRendering2D();
6154 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6155 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6156 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6157 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6158 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6164 matrix4x4_t r_waterscrollmatrix;
6166 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6168 if (r_refdef.fog_density)
6170 r_refdef.fogcolor[0] = r_refdef.fog_red;
6171 r_refdef.fogcolor[1] = r_refdef.fog_green;
6172 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6174 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6175 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6176 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6177 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6181 VectorCopy(r_refdef.fogcolor, fogvec);
6182 // color.rgb *= ContrastBoost * SceneBrightness;
6183 VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6184 r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6185 r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6186 r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6191 void R_UpdateVariables(void)
6195 r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6197 r_refdef.farclip = r_farclip_base.value;
6198 if (r_refdef.scene.worldmodel)
6199 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6200 r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6202 if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6203 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6204 r_refdef.polygonfactor = 0;
6205 r_refdef.polygonoffset = 0;
6206 r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6207 r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6209 r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6210 r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6211 r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6212 r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6213 r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6214 if (FAKELIGHT_ENABLED)
6216 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6218 if (r_showsurfaces.integer)
6220 r_refdef.scene.rtworld = false;
6221 r_refdef.scene.rtworldshadows = false;
6222 r_refdef.scene.rtdlight = false;
6223 r_refdef.scene.rtdlightshadows = false;
6224 r_refdef.lightmapintensity = 0;
6227 if (gamemode == GAME_NEHAHRA)
6229 if (gl_fogenable.integer)
6231 r_refdef.oldgl_fogenable = true;
6232 r_refdef.fog_density = gl_fogdensity.value;
6233 r_refdef.fog_red = gl_fogred.value;
6234 r_refdef.fog_green = gl_foggreen.value;
6235 r_refdef.fog_blue = gl_fogblue.value;
6236 r_refdef.fog_alpha = 1;
6237 r_refdef.fog_start = 0;
6238 r_refdef.fog_end = gl_skyclip.value;
6239 r_refdef.fog_height = 1<<30;
6240 r_refdef.fog_fadedepth = 128;
6242 else if (r_refdef.oldgl_fogenable)
6244 r_refdef.oldgl_fogenable = false;
6245 r_refdef.fog_density = 0;
6246 r_refdef.fog_red = 0;
6247 r_refdef.fog_green = 0;
6248 r_refdef.fog_blue = 0;
6249 r_refdef.fog_alpha = 0;
6250 r_refdef.fog_start = 0;
6251 r_refdef.fog_end = 0;
6252 r_refdef.fog_height = 1<<30;
6253 r_refdef.fog_fadedepth = 128;
6257 r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6258 r_refdef.fog_start = max(0, r_refdef.fog_start);
6259 r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6261 // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6263 if (r_refdef.fog_density && r_drawfog.integer)
6265 r_refdef.fogenabled = true;
6266 // this is the point where the fog reaches 0.9986 alpha, which we
6267 // consider a good enough cutoff point for the texture
6268 // (0.9986 * 256 == 255.6)
6269 if (r_fog_exp2.integer)
6270 r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6272 r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6273 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6274 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6275 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6276 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6277 R_BuildFogHeightTexture();
6278 // fog color was already set
6279 // update the fog texture
6280 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)
6281 R_BuildFogTexture();
6282 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6283 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6286 r_refdef.fogenabled = false;
6288 switch(vid.renderpath)
6290 case RENDERPATH_GL20:
6291 case RENDERPATH_D3D9:
6292 case RENDERPATH_D3D10:
6293 case RENDERPATH_D3D11:
6294 case RENDERPATH_SOFT:
6295 case RENDERPATH_GLES2:
6296 if(v_glslgamma.integer && !vid_gammatables_trivial)
6298 if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6300 // build GLSL gamma texture
6301 #define RAMPWIDTH 256
6302 unsigned short ramp[RAMPWIDTH * 3];
6303 unsigned char rampbgr[RAMPWIDTH][4];
6306 r_texture_gammaramps_serial = vid_gammatables_serial;
6308 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6309 for(i = 0; i < RAMPWIDTH; ++i)
6311 rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6312 rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6313 rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6316 if (r_texture_gammaramps)
6318 R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6322 r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6328 // remove GLSL gamma texture
6331 case RENDERPATH_GL13:
6332 case RENDERPATH_GL11:
6337 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6338 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6344 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6345 if( scenetype != r_currentscenetype ) {
6346 // store the old scenetype
6347 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6348 r_currentscenetype = scenetype;
6349 // move in the new scene
6350 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6359 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6361 // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6362 if( scenetype == r_currentscenetype ) {
6363 return &r_refdef.scene;
6365 return &r_scenes_store[ scenetype ];
6374 int dpsoftrast_test;
6375 void R_RenderView(void)
6377 matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6379 dpsoftrast_test = r_test.integer;
6381 if (r_timereport_active)
6382 R_TimeReport("start");
6383 r_textureframe++; // used only by R_GetCurrentTexture
6384 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6386 if(R_CompileShader_CheckStaticParms())
6389 if (!r_drawentities.integer)
6390 r_refdef.scene.numentities = 0;
6392 R_AnimCache_ClearCache();
6393 R_FrameData_NewFrame();
6395 /* adjust for stereo display */
6396 if(R_Stereo_Active())
6398 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);
6399 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6402 if (r_refdef.view.isoverlay)
6404 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6405 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6406 R_TimeReport("depthclear");
6408 r_refdef.view.showdebug = false;
6410 r_waterstate.enabled = false;
6411 r_waterstate.numwaterplanes = 0;
6415 r_refdef.view.matrix = originalmatrix;
6421 if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6423 r_refdef.view.matrix = originalmatrix;
6424 return; //Host_Error ("R_RenderView: NULL worldmodel");
6427 r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6429 R_RenderView_UpdateViewVectors();
6431 R_Shadow_UpdateWorldLightSelection();
6433 R_Bloom_StartFrame();
6434 R_Water_StartFrame();
6437 if (r_timereport_active)
6438 R_TimeReport("viewsetup");
6440 R_ResetViewRendering3D();
6442 if (r_refdef.view.clear || r_refdef.fogenabled)
6444 R_ClearScreen(r_refdef.fogenabled);
6445 if (r_timereport_active)
6446 R_TimeReport("viewclear");
6448 r_refdef.view.clear = true;
6450 // this produces a bloom texture to be used in R_BlendView() later
6451 if (r_hdr.integer && r_bloomstate.bloomwidth)
6453 R_HDR_RenderBloomTexture();
6454 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6455 r_textureframe++; // used only by R_GetCurrentTexture
6458 r_refdef.view.showdebug = true;
6461 if (r_timereport_active)
6462 R_TimeReport("visibility");
6464 r_waterstate.numwaterplanes = 0;
6465 if (r_waterstate.enabled)
6466 R_RenderWaterPlanes();
6469 r_waterstate.numwaterplanes = 0;
6472 if (r_timereport_active)
6473 R_TimeReport("blendview");
6475 GL_Scissor(0, 0, vid.width, vid.height);
6476 GL_ScissorTest(false);
6478 r_refdef.view.matrix = originalmatrix;
6483 void R_RenderWaterPlanes(void)
6485 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6487 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6488 if (r_timereport_active)
6489 R_TimeReport("waterworld");
6492 // don't let sound skip if going slow
6493 if (r_refdef.scene.extraupdate)
6496 R_DrawModelsAddWaterPlanes();
6497 if (r_timereport_active)
6498 R_TimeReport("watermodels");
6500 if (r_waterstate.numwaterplanes)
6502 R_Water_ProcessPlanes();
6503 if (r_timereport_active)
6504 R_TimeReport("waterscenes");
6508 extern void R_DrawLightningBeams (void);
6509 extern void VM_CL_AddPolygonsToMeshQueue (void);
6510 extern void R_DrawPortals (void);
6511 extern cvar_t cl_locs_show;
6512 static void R_DrawLocs(void);
6513 static void R_DrawEntityBBoxes(void);
6514 static void R_DrawModelDecals(void);
6515 extern void R_DrawModelShadows(void);
6516 extern void R_DrawModelShadowMaps(void);
6517 extern cvar_t cl_decals_newsystem;
6518 extern qboolean r_shadow_usingdeferredprepass;
6519 void R_RenderScene(void)
6521 qboolean shadowmapping = false;
6523 if (r_timereport_active)
6524 R_TimeReport("beginscene");
6526 r_refdef.stats.renders++;
6530 // don't let sound skip if going slow
6531 if (r_refdef.scene.extraupdate)
6534 R_MeshQueue_BeginScene();
6538 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);
6540 if (r_timereport_active)
6541 R_TimeReport("skystartframe");
6543 if (cl.csqc_vidvars.drawworld)
6545 // don't let sound skip if going slow
6546 if (r_refdef.scene.extraupdate)
6549 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6551 r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6552 if (r_timereport_active)
6553 R_TimeReport("worldsky");
6556 if (R_DrawBrushModelsSky() && r_timereport_active)
6557 R_TimeReport("bmodelsky");
6559 if (skyrendermasked && skyrenderlater)
6561 // we have to force off the water clipping plane while rendering sky
6565 if (r_timereport_active)
6566 R_TimeReport("sky");
6570 R_AnimCache_CacheVisibleEntities();
6571 if (r_timereport_active)
6572 R_TimeReport("animation");
6574 R_Shadow_PrepareLights();
6575 if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6576 R_Shadow_PrepareModelShadows();
6577 if (r_timereport_active)
6578 R_TimeReport("preparelights");
6580 if (R_Shadow_ShadowMappingEnabled())
6581 shadowmapping = true;
6583 if (r_shadow_usingdeferredprepass)
6584 R_Shadow_DrawPrepass();
6586 if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6588 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6589 if (r_timereport_active)
6590 R_TimeReport("worlddepth");
6592 if (r_depthfirst.integer >= 2)
6594 R_DrawModelsDepth();
6595 if (r_timereport_active)
6596 R_TimeReport("modeldepth");
6599 if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6601 R_DrawModelShadowMaps();
6602 R_ResetViewRendering3D();
6603 // don't let sound skip if going slow
6604 if (r_refdef.scene.extraupdate)
6608 if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6610 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6611 if (r_timereport_active)
6612 R_TimeReport("world");
6615 // don't let sound skip if going slow
6616 if (r_refdef.scene.extraupdate)
6620 if (r_timereport_active)
6621 R_TimeReport("models");
6623 // don't let sound skip if going slow
6624 if (r_refdef.scene.extraupdate)
6627 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6629 R_DrawModelShadows();
6630 R_ResetViewRendering3D();
6631 // don't let sound skip if going slow
6632 if (r_refdef.scene.extraupdate)
6636 if (!r_shadow_usingdeferredprepass)
6638 R_Shadow_DrawLights();
6639 if (r_timereport_active)
6640 R_TimeReport("rtlights");
6643 // don't let sound skip if going slow
6644 if (r_refdef.scene.extraupdate)
6647 if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6649 R_DrawModelShadows();
6650 R_ResetViewRendering3D();
6651 // don't let sound skip if going slow
6652 if (r_refdef.scene.extraupdate)
6656 if (cl.csqc_vidvars.drawworld)
6658 if (cl_decals_newsystem.integer)
6660 R_DrawModelDecals();
6661 if (r_timereport_active)
6662 R_TimeReport("modeldecals");
6667 if (r_timereport_active)
6668 R_TimeReport("decals");
6672 if (r_timereport_active)
6673 R_TimeReport("particles");
6676 if (r_timereport_active)
6677 R_TimeReport("explosions");
6679 R_DrawLightningBeams();
6680 if (r_timereport_active)
6681 R_TimeReport("lightning");
6684 VM_CL_AddPolygonsToMeshQueue();
6686 if (r_refdef.view.showdebug)
6688 if (cl_locs_show.integer)
6691 if (r_timereport_active)
6692 R_TimeReport("showlocs");
6695 if (r_drawportals.integer)
6698 if (r_timereport_active)
6699 R_TimeReport("portals");
6702 if (r_showbboxes.value > 0)
6704 R_DrawEntityBBoxes();
6705 if (r_timereport_active)
6706 R_TimeReport("bboxes");
6710 R_MeshQueue_RenderTransparent();
6711 if (r_timereport_active)
6712 R_TimeReport("drawtrans");
6714 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))
6716 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
6717 if (r_timereport_active)
6718 R_TimeReport("worlddebug");
6719 R_DrawModelsDebug();
6720 if (r_timereport_active)
6721 R_TimeReport("modeldebug");
6724 if (cl.csqc_vidvars.drawworld)
6726 R_Shadow_DrawCoronas();
6727 if (r_timereport_active)
6728 R_TimeReport("coronas");
6733 GL_DepthTest(false);
6734 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
6735 GL_Color(1, 1, 1, 1);
6736 qglBegin(GL_POLYGON);
6737 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
6738 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
6739 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
6740 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
6742 qglBegin(GL_POLYGON);
6743 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]);
6744 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]);
6745 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]);
6746 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]);
6748 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
6752 // don't let sound skip if going slow
6753 if (r_refdef.scene.extraupdate)
6756 R_ResetViewRendering2D();
6759 static const unsigned short bboxelements[36] =
6769 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
6772 float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
6774 RSurf_ActiveWorldEntity();
6776 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6777 GL_DepthMask(false);
6778 GL_DepthRange(0, 1);
6779 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
6780 // R_Mesh_ResetTextureState();
6782 vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
6783 vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
6784 vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
6785 vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
6786 vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
6787 vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
6788 vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
6789 vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
6790 R_FillColors(color4f, 8, cr, cg, cb, ca);
6791 if (r_refdef.fogenabled)
6793 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
6795 f1 = RSurf_FogVertex(v);
6797 c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
6798 c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
6799 c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
6802 R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
6803 R_Mesh_ResetTextureState();
6804 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6805 R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
6808 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6812 prvm_edict_t *edict;
6813 prvm_prog_t *prog_save = prog;
6815 // this function draws bounding boxes of server entities
6819 GL_CullFace(GL_NONE);
6820 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6824 for (i = 0;i < numsurfaces;i++)
6826 edict = PRVM_EDICT_NUM(surfacelist[i]);
6827 switch ((int)edict->fields.server->solid)
6829 case SOLID_NOT: Vector4Set(color, 1, 1, 1, 0.05);break;
6830 case SOLID_TRIGGER: Vector4Set(color, 1, 0, 1, 0.10);break;
6831 case SOLID_BBOX: Vector4Set(color, 0, 1, 0, 0.10);break;
6832 case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
6833 case SOLID_BSP: Vector4Set(color, 0, 0, 1, 0.05);break;
6834 default: Vector4Set(color, 0, 0, 0, 0.50);break;
6836 color[3] *= r_showbboxes.value;
6837 color[3] = bound(0, color[3], 1);
6838 GL_DepthTest(!r_showdisabledepthtest.integer);
6839 GL_CullFace(r_refdef.view.cullface_front);
6840 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
6846 static void R_DrawEntityBBoxes(void)
6849 prvm_edict_t *edict;
6851 prvm_prog_t *prog_save = prog;
6853 // this function draws bounding boxes of server entities
6859 for (i = 0;i < prog->num_edicts;i++)
6861 edict = PRVM_EDICT_NUM(i);
6862 if (edict->priv.server->free)
6864 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
6865 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
6867 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
6869 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
6870 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
6876 static const int nomodelelement3i[24] =
6888 static const unsigned short nomodelelement3s[24] =
6900 static const float nomodelvertex3f[6*3] =
6910 static const float nomodelcolor4f[6*4] =
6912 0.0f, 0.0f, 0.5f, 1.0f,
6913 0.0f, 0.0f, 0.5f, 1.0f,
6914 0.0f, 0.5f, 0.0f, 1.0f,
6915 0.0f, 0.5f, 0.0f, 1.0f,
6916 0.5f, 0.0f, 0.0f, 1.0f,
6917 0.5f, 0.0f, 0.0f, 1.0f
6920 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
6926 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);
6928 // this is only called once per entity so numsurfaces is always 1, and
6929 // surfacelist is always {0}, so this code does not handle batches
6931 if (rsurface.ent_flags & RENDER_ADDITIVE)
6933 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
6934 GL_DepthMask(false);
6936 else if (rsurface.colormod[3] < 1)
6938 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6939 GL_DepthMask(false);
6943 GL_BlendFunc(GL_ONE, GL_ZERO);
6946 GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
6947 GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
6948 GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
6949 GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
6950 memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
6951 for (i = 0, c = color4f;i < 6;i++, c += 4)
6953 c[0] *= rsurface.colormod[0];
6954 c[1] *= rsurface.colormod[1];
6955 c[2] *= rsurface.colormod[2];
6956 c[3] *= rsurface.colormod[3];
6958 if (r_refdef.fogenabled)
6960 for (i = 0, c = color4f;i < 6;i++, c += 4)
6962 f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
6964 c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
6965 c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
6966 c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
6969 // R_Mesh_ResetTextureState();
6970 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
6971 R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
6972 R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
6975 void R_DrawNoModel(entity_render_t *ent)
6978 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
6979 if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
6980 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
6982 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
6985 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
6987 vec3_t right1, right2, diff, normal;
6989 VectorSubtract (org2, org1, normal);
6991 // calculate 'right' vector for start
6992 VectorSubtract (r_refdef.view.origin, org1, diff);
6993 CrossProduct (normal, diff, right1);
6994 VectorNormalize (right1);
6996 // calculate 'right' vector for end
6997 VectorSubtract (r_refdef.view.origin, org2, diff);
6998 CrossProduct (normal, diff, right2);
6999 VectorNormalize (right2);
7001 vert[ 0] = org1[0] + width * right1[0];
7002 vert[ 1] = org1[1] + width * right1[1];
7003 vert[ 2] = org1[2] + width * right1[2];
7004 vert[ 3] = org1[0] - width * right1[0];
7005 vert[ 4] = org1[1] - width * right1[1];
7006 vert[ 5] = org1[2] - width * right1[2];
7007 vert[ 6] = org2[0] - width * right2[0];
7008 vert[ 7] = org2[1] - width * right2[1];
7009 vert[ 8] = org2[2] - width * right2[2];
7010 vert[ 9] = org2[0] + width * right2[0];
7011 vert[10] = org2[1] + width * right2[1];
7012 vert[11] = org2[2] + width * right2[2];
7015 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)
7017 vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7018 vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7019 vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7020 vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7021 vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7022 vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7023 vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7024 vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7025 vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7026 vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7027 vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7028 vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7031 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7036 VectorSet(v, x, y, z);
7037 for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7038 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7040 if (i == mesh->numvertices)
7042 if (mesh->numvertices < mesh->maxvertices)
7044 VectorCopy(v, vertex3f);
7045 mesh->numvertices++;
7047 return mesh->numvertices;
7053 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7057 element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7058 element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7059 e = mesh->element3i + mesh->numtriangles * 3;
7060 for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7062 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7063 if (mesh->numtriangles < mesh->maxtriangles)
7068 mesh->numtriangles++;
7070 element[1] = element[2];
7074 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7078 element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7079 element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7080 e = mesh->element3i + mesh->numtriangles * 3;
7081 for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7083 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7084 if (mesh->numtriangles < mesh->maxtriangles)
7089 mesh->numtriangles++;
7091 element[1] = element[2];
7095 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7096 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7098 int planenum, planenum2;
7101 mplane_t *plane, *plane2;
7103 double temppoints[2][256*3];
7104 // figure out how large a bounding box we need to properly compute this brush
7106 for (w = 0;w < numplanes;w++)
7107 maxdist = max(maxdist, fabs(planes[w].dist));
7108 // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7109 maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7110 for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7114 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7115 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7117 if (planenum2 == planenum)
7119 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);
7122 if (tempnumpoints < 3)
7124 // generate elements forming a triangle fan for this polygon
7125 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7129 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)
7131 texturelayer_t *layer;
7132 layer = t->currentlayers + t->currentnumlayers++;
7134 layer->depthmask = depthmask;
7135 layer->blendfunc1 = blendfunc1;
7136 layer->blendfunc2 = blendfunc2;
7137 layer->texture = texture;
7138 layer->texmatrix = *matrix;
7139 layer->color[0] = r;
7140 layer->color[1] = g;
7141 layer->color[2] = b;
7142 layer->color[3] = a;
7145 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7147 if(parms[0] == 0 && parms[1] == 0)
7149 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7150 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7155 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7158 index = parms[2] + r_refdef.scene.time * parms[3];
7159 index -= floor(index);
7160 switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7163 case Q3WAVEFUNC_NONE:
7164 case Q3WAVEFUNC_NOISE:
7165 case Q3WAVEFUNC_COUNT:
7168 case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7169 case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7170 case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7171 case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7172 case Q3WAVEFUNC_TRIANGLE:
7174 f = index - floor(index);
7185 f = parms[0] + parms[1] * f;
7186 if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7187 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7191 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7196 matrix4x4_t matrix, temp;
7197 switch(tcmod->tcmod)
7201 if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7202 matrix = r_waterscrollmatrix;
7204 matrix = identitymatrix;
7206 case Q3TCMOD_ENTITYTRANSLATE:
7207 // this is used in Q3 to allow the gamecode to control texcoord
7208 // scrolling on the entity, which is not supported in darkplaces yet.
7209 Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7211 case Q3TCMOD_ROTATE:
7212 Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7213 Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
7214 Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7217 Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7219 case Q3TCMOD_SCROLL:
7220 Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
7222 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7223 w = (int) tcmod->parms[0];
7224 h = (int) tcmod->parms[1];
7225 f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
7227 idx = (int) floor(f * w * h);
7228 Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7230 case Q3TCMOD_STRETCH:
7231 f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7232 Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7234 case Q3TCMOD_TRANSFORM:
7235 VectorSet(tcmat + 0, tcmod->parms[0], tcmod->parms[1], 0);
7236 VectorSet(tcmat + 3, tcmod->parms[2], tcmod->parms[3], 0);
7237 VectorSet(tcmat + 6, 0 , 0 , 1);
7238 VectorSet(tcmat + 9, tcmod->parms[4], tcmod->parms[5], 0);
7239 Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7241 case Q3TCMOD_TURBULENT:
7242 // this is handled in the RSurf_PrepareVertices function
7243 matrix = identitymatrix;
7247 Matrix4x4_Concat(texmatrix, &matrix, &temp);
7250 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7252 int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
7253 char name[MAX_QPATH];
7254 skinframe_t *skinframe;
7255 unsigned char pixels[296*194];
7256 strlcpy(cache->name, skinname, sizeof(cache->name));
7257 dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7258 if (developer_loading.integer)
7259 Con_Printf("loading %s\n", name);
7260 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7261 if (!skinframe || !skinframe->base)
7264 fs_offset_t filesize;
7266 f = FS_LoadFile(name, tempmempool, true, &filesize);
7269 if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7270 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7274 cache->skinframe = skinframe;
7277 texture_t *R_GetCurrentTexture(texture_t *t)
7280 const entity_render_t *ent = rsurface.entity;
7281 dp_model_t *model = ent->model;
7282 q3shaderinfo_layer_tcmod_t *tcmod;
7284 if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7285 return t->currentframe;
7286 t->update_lastrenderframe = r_textureframe;
7287 t->update_lastrenderentity = (void *)ent;
7289 if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7290 t->camera_entity = ent->entitynumber;
7292 t->camera_entity = 0;
7294 // switch to an alternate material if this is a q1bsp animated material
7296 texture_t *texture = t;
7297 int s = rsurface.ent_skinnum;
7298 if ((unsigned int)s >= (unsigned int)model->numskins)
7300 if (model->skinscenes)
7302 if (model->skinscenes[s].framecount > 1)
7303 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7305 s = model->skinscenes[s].firstframe;
7308 t = t + s * model->num_surfaces;
7311 // use an alternate animation if the entity's frame is not 0,
7312 // and only if the texture has an alternate animation
7313 if (rsurface.ent_alttextures && t->anim_total[1])
7314 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
7316 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
7318 texture->currentframe = t;
7321 // update currentskinframe to be a qw skin or animation frame
7322 if (rsurface.ent_qwskin >= 0)
7324 i = rsurface.ent_qwskin;
7325 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7327 r_qwskincache_size = cl.maxclients;
7329 Mem_Free(r_qwskincache);
7330 r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7332 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7333 R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7334 t->currentskinframe = r_qwskincache[i].skinframe;
7335 if (t->currentskinframe == NULL)
7336 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7338 else if (t->numskinframes >= 2)
7339 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
7340 if (t->backgroundnumskinframes >= 2)
7341 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
7343 t->currentmaterialflags = t->basematerialflags;
7344 t->currentalpha = rsurface.colormod[3];
7345 if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
7346 t->currentalpha *= r_wateralpha.value;
7347 if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7348 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7349 if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7350 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7351 if (!(rsurface.ent_flags & RENDER_LIGHT))
7352 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7353 else if (FAKELIGHT_ENABLED)
7355 // no modellight if using fakelight for the map
7357 else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7359 // pick a model lighting mode
7360 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7361 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7363 t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7365 if (rsurface.ent_flags & RENDER_ADDITIVE)
7366 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7367 else if (t->currentalpha < 1)
7368 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7369 if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7370 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7371 if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7372 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7373 if (t->backgroundnumskinframes)
7374 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7375 if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7377 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7378 t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7381 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7382 if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7383 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7385 // there is no tcmod
7386 if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7388 t->currenttexmatrix = r_waterscrollmatrix;
7389 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7391 else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7393 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7394 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7397 for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7398 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7399 for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7400 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7402 t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7403 if (t->currentskinframe->qpixels)
7404 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7405 t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7406 if (!t->basetexture)
7407 t->basetexture = r_texture_notexture;
7408 t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7409 t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7410 t->nmaptexture = t->currentskinframe->nmap;
7411 if (!t->nmaptexture)
7412 t->nmaptexture = r_texture_blanknormalmap;
7413 t->glosstexture = r_texture_black;
7414 t->glowtexture = t->currentskinframe->glow;
7415 t->fogtexture = t->currentskinframe->fog;
7416 t->reflectmasktexture = t->currentskinframe->reflect;
7417 if (t->backgroundnumskinframes)
7419 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7420 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7421 t->backgroundglosstexture = r_texture_black;
7422 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7423 if (!t->backgroundnmaptexture)
7424 t->backgroundnmaptexture = r_texture_blanknormalmap;
7428 t->backgroundbasetexture = r_texture_white;
7429 t->backgroundnmaptexture = r_texture_blanknormalmap;
7430 t->backgroundglosstexture = r_texture_black;
7431 t->backgroundglowtexture = NULL;
7433 t->specularpower = r_shadow_glossexponent.value;
7434 // TODO: store reference values for these in the texture?
7435 t->specularscale = 0;
7436 if (r_shadow_gloss.integer > 0)
7438 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7440 if (r_shadow_glossintensity.value > 0)
7442 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7443 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7444 t->specularscale = r_shadow_glossintensity.value;
7447 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7449 t->glosstexture = r_texture_white;
7450 t->backgroundglosstexture = r_texture_white;
7451 t->specularscale = r_shadow_gloss2intensity.value;
7452 t->specularpower = r_shadow_gloss2exponent.value;
7455 t->specularscale *= t->specularscalemod;
7456 t->specularpower *= t->specularpowermod;
7458 // lightmaps mode looks bad with dlights using actual texturing, so turn
7459 // off the colormap and glossmap, but leave the normalmap on as it still
7460 // accurately represents the shading involved
7461 if (gl_lightmaps.integer)
7463 t->basetexture = r_texture_grey128;
7464 t->pantstexture = r_texture_black;
7465 t->shirttexture = r_texture_black;
7466 t->nmaptexture = r_texture_blanknormalmap;
7467 t->glosstexture = r_texture_black;
7468 t->glowtexture = NULL;
7469 t->fogtexture = NULL;
7470 t->reflectmasktexture = NULL;
7471 t->backgroundbasetexture = NULL;
7472 t->backgroundnmaptexture = r_texture_blanknormalmap;
7473 t->backgroundglosstexture = r_texture_black;
7474 t->backgroundglowtexture = NULL;
7475 t->specularscale = 0;
7476 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7479 Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7480 VectorClear(t->dlightcolor);
7481 t->currentnumlayers = 0;
7482 if (t->currentmaterialflags & MATERIALFLAG_WALL)
7484 int blendfunc1, blendfunc2;
7486 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7488 blendfunc1 = GL_SRC_ALPHA;
7489 blendfunc2 = GL_ONE;
7491 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7493 blendfunc1 = GL_SRC_ALPHA;
7494 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7496 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7498 blendfunc1 = t->customblendfunc[0];
7499 blendfunc2 = t->customblendfunc[1];
7503 blendfunc1 = GL_ONE;
7504 blendfunc2 = GL_ZERO;
7506 // don't colormod evilblend textures
7507 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7508 VectorSet(t->lightmapcolor, 1, 1, 1);
7509 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7510 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7512 // fullbright is not affected by r_refdef.lightmapintensity
7513 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]);
7514 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7515 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]);
7516 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7517 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]);
7521 vec3_t ambientcolor;
7523 // set the color tint used for lights affecting this surface
7524 VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7526 // q3bsp has no lightmap updates, so the lightstylevalue that
7527 // would normally be baked into the lightmap must be
7528 // applied to the color
7529 // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7530 if (model->type == mod_brushq3)
7531 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7532 colorscale *= r_refdef.lightmapintensity;
7533 VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7534 VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7535 // basic lit geometry
7536 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]);
7537 // add pants/shirt if needed
7538 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7539 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]);
7540 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7541 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]);
7542 // now add ambient passes if needed
7543 if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7545 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]);
7546 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7547 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]);
7548 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7549 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]);
7552 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7553 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]);
7554 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7556 // if this is opaque use alpha blend which will darken the earlier
7559 // if this is an alpha blended material, all the earlier passes
7560 // were darkened by fog already, so we only need to add the fog
7561 // color ontop through the fog mask texture
7563 // if this is an additive blended material, all the earlier passes
7564 // were darkened by fog already, and we should not add fog color
7565 // (because the background was not darkened, there is no fog color
7566 // that was lost behind it).
7567 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]);
7571 return t->currentframe;
7574 rsurfacestate_t rsurface;
7576 void RSurf_ActiveWorldEntity(void)
7578 dp_model_t *model = r_refdef.scene.worldmodel;
7579 //if (rsurface.entity == r_refdef.scene.worldentity)
7581 rsurface.entity = r_refdef.scene.worldentity;
7582 rsurface.skeleton = NULL;
7583 memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7584 rsurface.ent_skinnum = 0;
7585 rsurface.ent_qwskin = -1;
7586 rsurface.ent_shadertime = 0;
7587 rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7588 rsurface.matrix = identitymatrix;
7589 rsurface.inversematrix = identitymatrix;
7590 rsurface.matrixscale = 1;
7591 rsurface.inversematrixscale = 1;
7592 R_EntityMatrix(&identitymatrix);
7593 VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7594 Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7595 rsurface.fograngerecip = r_refdef.fograngerecip;
7596 rsurface.fogheightfade = r_refdef.fogheightfade;
7597 rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7598 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7599 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7600 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7601 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7602 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7603 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7604 VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7605 rsurface.colormod[3] = 1;
7606 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);
7607 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7608 rsurface.frameblend[0].lerp = 1;
7609 rsurface.ent_alttextures = false;
7610 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7611 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7612 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7613 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7614 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7615 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7616 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7617 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7618 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7619 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7620 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7621 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7622 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7623 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7624 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7625 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7626 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7627 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7628 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7629 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7630 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7631 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7632 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7633 rsurface.modelelement3i = model->surfmesh.data_element3i;
7634 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7635 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7636 rsurface.modelelement3s = model->surfmesh.data_element3s;
7637 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7638 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7639 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7640 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7641 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7642 rsurface.modelsurfaces = model->data_surfaces;
7643 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7644 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7645 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7646 rsurface.modelgeneratedvertex = false;
7647 rsurface.batchgeneratedvertex = false;
7648 rsurface.batchfirstvertex = 0;
7649 rsurface.batchnumvertices = 0;
7650 rsurface.batchfirsttriangle = 0;
7651 rsurface.batchnumtriangles = 0;
7652 rsurface.batchvertex3f = NULL;
7653 rsurface.batchvertex3f_vertexbuffer = NULL;
7654 rsurface.batchvertex3f_bufferoffset = 0;
7655 rsurface.batchsvector3f = NULL;
7656 rsurface.batchsvector3f_vertexbuffer = NULL;
7657 rsurface.batchsvector3f_bufferoffset = 0;
7658 rsurface.batchtvector3f = NULL;
7659 rsurface.batchtvector3f_vertexbuffer = NULL;
7660 rsurface.batchtvector3f_bufferoffset = 0;
7661 rsurface.batchnormal3f = NULL;
7662 rsurface.batchnormal3f_vertexbuffer = NULL;
7663 rsurface.batchnormal3f_bufferoffset = 0;
7664 rsurface.batchlightmapcolor4f = NULL;
7665 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7666 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7667 rsurface.batchtexcoordtexture2f = NULL;
7668 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7669 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7670 rsurface.batchtexcoordlightmap2f = NULL;
7671 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7672 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7673 rsurface.batchvertexmesh = NULL;
7674 rsurface.batchvertexmeshbuffer = NULL;
7675 rsurface.batchvertex3fbuffer = NULL;
7676 rsurface.batchelement3i = NULL;
7677 rsurface.batchelement3i_indexbuffer = NULL;
7678 rsurface.batchelement3i_bufferoffset = 0;
7679 rsurface.batchelement3s = NULL;
7680 rsurface.batchelement3s_indexbuffer = NULL;
7681 rsurface.batchelement3s_bufferoffset = 0;
7682 rsurface.passcolor4f = NULL;
7683 rsurface.passcolor4f_vertexbuffer = NULL;
7684 rsurface.passcolor4f_bufferoffset = 0;
7687 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
7689 dp_model_t *model = ent->model;
7690 //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
7692 rsurface.entity = (entity_render_t *)ent;
7693 rsurface.skeleton = ent->skeleton;
7694 memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
7695 rsurface.ent_skinnum = ent->skinnum;
7696 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;
7697 rsurface.ent_shadertime = ent->shadertime;
7698 rsurface.ent_flags = ent->flags;
7699 rsurface.matrix = ent->matrix;
7700 rsurface.inversematrix = ent->inversematrix;
7701 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7702 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7703 R_EntityMatrix(&rsurface.matrix);
7704 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7705 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7706 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7707 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7708 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7709 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7710 VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
7711 VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
7712 VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
7713 VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
7714 VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
7715 VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
7716 rsurface.colormod[3] = ent->alpha;
7717 VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
7718 memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
7719 rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
7720 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7721 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7722 if (ent->model->brush.submodel && !prepass)
7724 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
7725 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
7727 if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
7729 if (ent->animcache_vertex3f)
7731 rsurface.modelvertex3f = ent->animcache_vertex3f;
7732 rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
7733 rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
7734 rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
7735 rsurface.modelvertexmesh = ent->animcache_vertexmesh;
7736 rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
7737 rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
7739 else if (wanttangents)
7741 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7742 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7743 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7744 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7745 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
7746 rsurface.modelvertexmesh = NULL;
7747 rsurface.modelvertexmeshbuffer = NULL;
7748 rsurface.modelvertex3fbuffer = NULL;
7750 else if (wantnormals)
7752 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7753 rsurface.modelsvector3f = NULL;
7754 rsurface.modeltvector3f = NULL;
7755 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7756 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
7757 rsurface.modelvertexmesh = NULL;
7758 rsurface.modelvertexmeshbuffer = NULL;
7759 rsurface.modelvertex3fbuffer = NULL;
7763 rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
7764 rsurface.modelsvector3f = NULL;
7765 rsurface.modeltvector3f = NULL;
7766 rsurface.modelnormal3f = NULL;
7767 model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
7768 rsurface.modelvertexmesh = NULL;
7769 rsurface.modelvertexmeshbuffer = NULL;
7770 rsurface.modelvertex3fbuffer = NULL;
7772 rsurface.modelvertex3f_vertexbuffer = 0;
7773 rsurface.modelvertex3f_bufferoffset = 0;
7774 rsurface.modelsvector3f_vertexbuffer = 0;
7775 rsurface.modelsvector3f_bufferoffset = 0;
7776 rsurface.modeltvector3f_vertexbuffer = 0;
7777 rsurface.modeltvector3f_bufferoffset = 0;
7778 rsurface.modelnormal3f_vertexbuffer = 0;
7779 rsurface.modelnormal3f_bufferoffset = 0;
7780 rsurface.modelgeneratedvertex = true;
7784 rsurface.modelvertex3f = model->surfmesh.data_vertex3f;
7785 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7786 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7787 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7788 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7789 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7790 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7791 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7792 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7793 rsurface.modelnormal3f = model->surfmesh.data_normal3f;
7794 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7795 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7796 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7797 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7798 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7799 rsurface.modelgeneratedvertex = false;
7801 rsurface.modellightmapcolor4f = model->surfmesh.data_lightmapcolor4f;
7802 rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7803 rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7804 rsurface.modeltexcoordtexture2f = model->surfmesh.data_texcoordtexture2f;
7805 rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7806 rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7807 rsurface.modeltexcoordlightmap2f = model->surfmesh.data_texcoordlightmap2f;
7808 rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7809 rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7810 rsurface.modelelement3i = model->surfmesh.data_element3i;
7811 rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7812 rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7813 rsurface.modelelement3s = model->surfmesh.data_element3s;
7814 rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7815 rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7816 rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7817 rsurface.modelnumvertices = model->surfmesh.num_vertices;
7818 rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7819 rsurface.modelsurfaces = model->data_surfaces;
7820 rsurface.batchgeneratedvertex = false;
7821 rsurface.batchfirstvertex = 0;
7822 rsurface.batchnumvertices = 0;
7823 rsurface.batchfirsttriangle = 0;
7824 rsurface.batchnumtriangles = 0;
7825 rsurface.batchvertex3f = NULL;
7826 rsurface.batchvertex3f_vertexbuffer = NULL;
7827 rsurface.batchvertex3f_bufferoffset = 0;
7828 rsurface.batchsvector3f = NULL;
7829 rsurface.batchsvector3f_vertexbuffer = NULL;
7830 rsurface.batchsvector3f_bufferoffset = 0;
7831 rsurface.batchtvector3f = NULL;
7832 rsurface.batchtvector3f_vertexbuffer = NULL;
7833 rsurface.batchtvector3f_bufferoffset = 0;
7834 rsurface.batchnormal3f = NULL;
7835 rsurface.batchnormal3f_vertexbuffer = NULL;
7836 rsurface.batchnormal3f_bufferoffset = 0;
7837 rsurface.batchlightmapcolor4f = NULL;
7838 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7839 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7840 rsurface.batchtexcoordtexture2f = NULL;
7841 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7842 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7843 rsurface.batchtexcoordlightmap2f = NULL;
7844 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7845 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7846 rsurface.batchvertexmesh = NULL;
7847 rsurface.batchvertexmeshbuffer = NULL;
7848 rsurface.batchvertex3fbuffer = NULL;
7849 rsurface.batchelement3i = NULL;
7850 rsurface.batchelement3i_indexbuffer = NULL;
7851 rsurface.batchelement3i_bufferoffset = 0;
7852 rsurface.batchelement3s = NULL;
7853 rsurface.batchelement3s_indexbuffer = NULL;
7854 rsurface.batchelement3s_bufferoffset = 0;
7855 rsurface.passcolor4f = NULL;
7856 rsurface.passcolor4f_vertexbuffer = NULL;
7857 rsurface.passcolor4f_bufferoffset = 0;
7860 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)
7862 rsurface.entity = r_refdef.scene.worldentity;
7863 rsurface.skeleton = NULL;
7864 rsurface.ent_skinnum = 0;
7865 rsurface.ent_qwskin = -1;
7866 rsurface.ent_shadertime = shadertime;
7867 rsurface.ent_flags = entflags;
7868 rsurface.modelnumvertices = numvertices;
7869 rsurface.modelnumtriangles = numtriangles;
7870 rsurface.matrix = *matrix;
7871 rsurface.inversematrix = *inversematrix;
7872 rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
7873 rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
7874 R_EntityMatrix(&rsurface.matrix);
7875 Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
7876 Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
7877 rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
7878 rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
7879 rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
7880 rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7881 VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7882 VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7883 VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7884 VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7885 VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7886 Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
7887 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);
7888 memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7889 rsurface.frameblend[0].lerp = 1;
7890 rsurface.ent_alttextures = false;
7891 rsurface.basepolygonfactor = r_refdef.polygonfactor;
7892 rsurface.basepolygonoffset = r_refdef.polygonoffset;
7895 rsurface.modelvertex3f = (float *)vertex3f;
7896 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7897 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7898 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7900 else if (wantnormals)
7902 rsurface.modelvertex3f = (float *)vertex3f;
7903 rsurface.modelsvector3f = NULL;
7904 rsurface.modeltvector3f = NULL;
7905 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7909 rsurface.modelvertex3f = (float *)vertex3f;
7910 rsurface.modelsvector3f = NULL;
7911 rsurface.modeltvector3f = NULL;
7912 rsurface.modelnormal3f = NULL;
7914 rsurface.modelvertexmesh = NULL;
7915 rsurface.modelvertexmeshbuffer = NULL;
7916 rsurface.modelvertex3fbuffer = NULL;
7917 rsurface.modelvertex3f_vertexbuffer = 0;
7918 rsurface.modelvertex3f_bufferoffset = 0;
7919 rsurface.modelsvector3f_vertexbuffer = 0;
7920 rsurface.modelsvector3f_bufferoffset = 0;
7921 rsurface.modeltvector3f_vertexbuffer = 0;
7922 rsurface.modeltvector3f_bufferoffset = 0;
7923 rsurface.modelnormal3f_vertexbuffer = 0;
7924 rsurface.modelnormal3f_bufferoffset = 0;
7925 rsurface.modelgeneratedvertex = true;
7926 rsurface.modellightmapcolor4f = (float *)color4f;
7927 rsurface.modellightmapcolor4f_vertexbuffer = 0;
7928 rsurface.modellightmapcolor4f_bufferoffset = 0;
7929 rsurface.modeltexcoordtexture2f = (float *)texcoord2f;
7930 rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
7931 rsurface.modeltexcoordtexture2f_bufferoffset = 0;
7932 rsurface.modeltexcoordlightmap2f = NULL;
7933 rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
7934 rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
7935 rsurface.modelelement3i = (int *)element3i;
7936 rsurface.modelelement3i_indexbuffer = NULL;
7937 rsurface.modelelement3i_bufferoffset = 0;
7938 rsurface.modelelement3s = (unsigned short *)element3s;
7939 rsurface.modelelement3s_indexbuffer = NULL;
7940 rsurface.modelelement3s_bufferoffset = 0;
7941 rsurface.modellightmapoffsets = NULL;
7942 rsurface.modelsurfaces = NULL;
7943 rsurface.batchgeneratedvertex = false;
7944 rsurface.batchfirstvertex = 0;
7945 rsurface.batchnumvertices = 0;
7946 rsurface.batchfirsttriangle = 0;
7947 rsurface.batchnumtriangles = 0;
7948 rsurface.batchvertex3f = NULL;
7949 rsurface.batchvertex3f_vertexbuffer = NULL;
7950 rsurface.batchvertex3f_bufferoffset = 0;
7951 rsurface.batchsvector3f = NULL;
7952 rsurface.batchsvector3f_vertexbuffer = NULL;
7953 rsurface.batchsvector3f_bufferoffset = 0;
7954 rsurface.batchtvector3f = NULL;
7955 rsurface.batchtvector3f_vertexbuffer = NULL;
7956 rsurface.batchtvector3f_bufferoffset = 0;
7957 rsurface.batchnormal3f = NULL;
7958 rsurface.batchnormal3f_vertexbuffer = NULL;
7959 rsurface.batchnormal3f_bufferoffset = 0;
7960 rsurface.batchlightmapcolor4f = NULL;
7961 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7962 rsurface.batchlightmapcolor4f_bufferoffset = 0;
7963 rsurface.batchtexcoordtexture2f = NULL;
7964 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7965 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7966 rsurface.batchtexcoordlightmap2f = NULL;
7967 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7968 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7969 rsurface.batchvertexmesh = NULL;
7970 rsurface.batchvertexmeshbuffer = NULL;
7971 rsurface.batchvertex3fbuffer = NULL;
7972 rsurface.batchelement3i = NULL;
7973 rsurface.batchelement3i_indexbuffer = NULL;
7974 rsurface.batchelement3i_bufferoffset = 0;
7975 rsurface.batchelement3s = NULL;
7976 rsurface.batchelement3s_indexbuffer = NULL;
7977 rsurface.batchelement3s_bufferoffset = 0;
7978 rsurface.passcolor4f = NULL;
7979 rsurface.passcolor4f_vertexbuffer = NULL;
7980 rsurface.passcolor4f_bufferoffset = 0;
7982 if (rsurface.modelnumvertices && rsurface.modelelement3i)
7984 if ((wantnormals || wanttangents) && !normal3f)
7986 rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7987 Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
7989 if (wanttangents && !svector3f)
7991 rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7992 rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
7993 Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
7998 float RSurf_FogPoint(const float *v)
8000 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8001 float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8002 float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8003 float FogHeightFade = r_refdef.fogheightfade;
8005 unsigned int fogmasktableindex;
8006 if (r_refdef.fogplaneviewabove)
8007 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8009 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8010 fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8011 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8014 float RSurf_FogVertex(const float *v)
8016 // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8017 float FogPlaneViewDist = rsurface.fogplaneviewdist;
8018 float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8019 float FogHeightFade = rsurface.fogheightfade;
8021 unsigned int fogmasktableindex;
8022 if (r_refdef.fogplaneviewabove)
8023 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8025 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8026 fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8027 return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8030 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8033 for (i = 0;i < numelements;i++)
8034 outelement3i[i] = inelement3i[i] + adjust;
8037 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8038 extern cvar_t gl_vbo;
8039 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8047 int surfacefirsttriangle;
8048 int surfacenumtriangles;
8049 int surfacefirstvertex;
8050 int surfaceendvertex;
8051 int surfacenumvertices;
8052 int batchnumvertices;
8053 int batchnumtriangles;
8057 qboolean dynamicvertex;
8061 float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8063 q3shaderinfo_deform_t *deform;
8064 const msurface_t *surface, *firstsurface;
8065 r_vertexmesh_t *vertexmesh;
8066 if (!texturenumsurfaces)
8068 // find vertex range of this surface batch
8070 firstsurface = texturesurfacelist[0];
8071 firsttriangle = firstsurface->num_firsttriangle;
8072 batchnumvertices = 0;
8073 batchnumtriangles = 0;
8074 firstvertex = endvertex = firstsurface->num_firstvertex;
8075 for (i = 0;i < texturenumsurfaces;i++)
8077 surface = texturesurfacelist[i];
8078 if (surface != firstsurface + i)
8080 surfacefirstvertex = surface->num_firstvertex;
8081 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8082 surfacenumvertices = surface->num_vertices;
8083 surfacenumtriangles = surface->num_triangles;
8084 if (firstvertex > surfacefirstvertex)
8085 firstvertex = surfacefirstvertex;
8086 if (endvertex < surfaceendvertex)
8087 endvertex = surfaceendvertex;
8088 batchnumvertices += surfacenumvertices;
8089 batchnumtriangles += surfacenumtriangles;
8092 // we now know the vertex range used, and if there are any gaps in it
8093 rsurface.batchfirstvertex = firstvertex;
8094 rsurface.batchnumvertices = endvertex - firstvertex;
8095 rsurface.batchfirsttriangle = firsttriangle;
8096 rsurface.batchnumtriangles = batchnumtriangles;
8098 // this variable holds flags for which properties have been updated that
8099 // may require regenerating vertexmesh array...
8102 // check if any dynamic vertex processing must occur
8103 dynamicvertex = false;
8105 // if there is a chance of animated vertex colors, it's a dynamic batch
8106 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8108 dynamicvertex = true;
8109 batchneed |= BATCHNEED_NOGAPS;
8110 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8113 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8115 switch (deform->deform)
8118 case Q3DEFORM_PROJECTIONSHADOW:
8119 case Q3DEFORM_TEXT0:
8120 case Q3DEFORM_TEXT1:
8121 case Q3DEFORM_TEXT2:
8122 case Q3DEFORM_TEXT3:
8123 case Q3DEFORM_TEXT4:
8124 case Q3DEFORM_TEXT5:
8125 case Q3DEFORM_TEXT6:
8126 case Q3DEFORM_TEXT7:
8129 case Q3DEFORM_AUTOSPRITE:
8130 dynamicvertex = true;
8131 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8132 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8134 case Q3DEFORM_AUTOSPRITE2:
8135 dynamicvertex = true;
8136 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8137 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8139 case Q3DEFORM_NORMAL:
8140 dynamicvertex = true;
8141 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8142 needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8145 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8146 break; // if wavefunc is a nop, ignore this transform
8147 dynamicvertex = true;
8148 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8149 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8151 case Q3DEFORM_BULGE:
8152 dynamicvertex = true;
8153 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8154 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8157 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8158 break; // if wavefunc is a nop, ignore this transform
8159 dynamicvertex = true;
8160 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8161 needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8165 switch(rsurface.texture->tcgen.tcgen)
8168 case Q3TCGEN_TEXTURE:
8170 case Q3TCGEN_LIGHTMAP:
8171 dynamicvertex = true;
8172 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8173 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8175 case Q3TCGEN_VECTOR:
8176 dynamicvertex = true;
8177 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8178 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8180 case Q3TCGEN_ENVIRONMENT:
8181 dynamicvertex = true;
8182 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8183 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8186 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8188 dynamicvertex = true;
8189 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8190 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8193 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8195 dynamicvertex = true;
8196 batchneed |= BATCHNEED_NOGAPS;
8197 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8200 if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8202 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8203 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX) batchneed |= BATCHNEED_ARRAY_VERTEX;
8204 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL) batchneed |= BATCHNEED_ARRAY_NORMAL;
8205 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR) batchneed |= BATCHNEED_ARRAY_VECTOR;
8206 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8207 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD) batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8208 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8211 // when the model data has no vertex buffer (dynamic mesh), we need to
8213 if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8214 batchneed |= BATCHNEED_NOGAPS;
8216 // if needsupdate, we have to do a dynamic vertex batch for sure
8217 if (needsupdate & batchneed)
8218 dynamicvertex = true;
8220 // see if we need to build vertexmesh from arrays
8221 if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8222 dynamicvertex = true;
8224 // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8225 // also some drivers strongly dislike firstvertex
8226 if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8227 dynamicvertex = true;
8229 rsurface.batchvertex3f = rsurface.modelvertex3f;
8230 rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8231 rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8232 rsurface.batchsvector3f = rsurface.modelsvector3f;
8233 rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8234 rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8235 rsurface.batchtvector3f = rsurface.modeltvector3f;
8236 rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8237 rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8238 rsurface.batchnormal3f = rsurface.modelnormal3f;
8239 rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8240 rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8241 rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8242 rsurface.batchlightmapcolor4f_vertexbuffer = rsurface.modellightmapcolor4f_vertexbuffer;
8243 rsurface.batchlightmapcolor4f_bufferoffset = rsurface.modellightmapcolor4f_bufferoffset;
8244 rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8245 rsurface.batchtexcoordtexture2f_vertexbuffer = rsurface.modeltexcoordtexture2f_vertexbuffer;
8246 rsurface.batchtexcoordtexture2f_bufferoffset = rsurface.modeltexcoordtexture2f_bufferoffset;
8247 rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8248 rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8249 rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8250 rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8251 rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8252 rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8253 rsurface.batchelement3i = rsurface.modelelement3i;
8254 rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8255 rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8256 rsurface.batchelement3s = rsurface.modelelement3s;
8257 rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8258 rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8260 // if any dynamic vertex processing has to occur in software, we copy the
8261 // entire surface list together before processing to rebase the vertices
8262 // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8264 // if any gaps exist and we do not have a static vertex buffer, we have to
8265 // copy the surface list together to avoid wasting upload bandwidth on the
8266 // vertices in the gaps.
8268 // if gaps exist and we have a static vertex buffer, we still have to
8269 // combine the index buffer ranges into one dynamic index buffer.
8271 // in all cases we end up with data that can be drawn in one call.
8275 // static vertex data, just set pointers...
8276 rsurface.batchgeneratedvertex = false;
8277 // if there are gaps, we want to build a combined index buffer,
8278 // otherwise use the original static buffer with an appropriate offset
8281 // build a new triangle elements array for this batch
8282 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8283 rsurface.batchfirsttriangle = 0;
8285 for (i = 0;i < texturenumsurfaces;i++)
8287 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8288 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8289 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8290 numtriangles += surfacenumtriangles;
8292 rsurface.batchelement3i_indexbuffer = NULL;
8293 rsurface.batchelement3i_bufferoffset = 0;
8294 rsurface.batchelement3s = NULL;
8295 rsurface.batchelement3s_indexbuffer = NULL;
8296 rsurface.batchelement3s_bufferoffset = 0;
8297 if (endvertex <= 65536)
8299 // make a 16bit (unsigned short) index array if possible
8300 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8301 for (i = 0;i < numtriangles*3;i++)
8302 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8308 // something needs software processing, do it for real...
8309 // we only directly handle separate array data in this case and then
8310 // generate interleaved data if needed...
8311 rsurface.batchgeneratedvertex = true;
8313 // now copy the vertex data into a combined array and make an index array
8314 // (this is what Quake3 does all the time)
8315 //if (gaps || rsurface.batchfirstvertex)
8317 rsurface.batchvertex3fbuffer = NULL;
8318 rsurface.batchvertexmesh = NULL;
8319 rsurface.batchvertexmeshbuffer = NULL;
8320 rsurface.batchvertex3f = NULL;
8321 rsurface.batchvertex3f_vertexbuffer = NULL;
8322 rsurface.batchvertex3f_bufferoffset = 0;
8323 rsurface.batchsvector3f = NULL;
8324 rsurface.batchsvector3f_vertexbuffer = NULL;
8325 rsurface.batchsvector3f_bufferoffset = 0;
8326 rsurface.batchtvector3f = NULL;
8327 rsurface.batchtvector3f_vertexbuffer = NULL;
8328 rsurface.batchtvector3f_bufferoffset = 0;
8329 rsurface.batchnormal3f = NULL;
8330 rsurface.batchnormal3f_vertexbuffer = NULL;
8331 rsurface.batchnormal3f_bufferoffset = 0;
8332 rsurface.batchlightmapcolor4f = NULL;
8333 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8334 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8335 rsurface.batchtexcoordtexture2f = NULL;
8336 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8337 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8338 rsurface.batchtexcoordlightmap2f = NULL;
8339 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8340 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8341 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8342 rsurface.batchelement3i_indexbuffer = NULL;
8343 rsurface.batchelement3i_bufferoffset = 0;
8344 rsurface.batchelement3s = NULL;
8345 rsurface.batchelement3s_indexbuffer = NULL;
8346 rsurface.batchelement3s_bufferoffset = 0;
8347 // we'll only be setting up certain arrays as needed
8348 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8349 rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8350 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8351 rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8352 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8353 rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8354 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8356 rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8357 rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8359 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8360 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8361 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8362 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8363 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8364 rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8367 for (i = 0;i < texturenumsurfaces;i++)
8369 surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8370 surfacenumvertices = texturesurfacelist[i]->num_vertices;
8371 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8372 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8373 // copy only the data requested
8374 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8375 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8376 if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8378 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8379 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8380 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
8381 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8382 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
8384 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8385 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8387 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
8388 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8389 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
8390 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8391 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
8392 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8394 RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8395 numvertices += surfacenumvertices;
8396 numtriangles += surfacenumtriangles;
8399 // generate a 16bit index array as well if possible
8400 // (in general, dynamic batches fit)
8401 if (numvertices <= 65536)
8403 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8404 for (i = 0;i < numtriangles*3;i++)
8405 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8408 // since we've copied everything, the batch now starts at 0
8409 rsurface.batchfirstvertex = 0;
8410 rsurface.batchnumvertices = batchnumvertices;
8411 rsurface.batchfirsttriangle = 0;
8412 rsurface.batchnumtriangles = batchnumtriangles;
8415 // q1bsp surfaces rendered in vertex color mode have to have colors
8416 // calculated based on lightstyles
8417 if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8419 // generate color arrays for the surfaces in this list
8424 const unsigned char *lm;
8425 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8426 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8427 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8429 for (i = 0;i < texturenumsurfaces;i++)
8431 surface = texturesurfacelist[i];
8432 offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8433 surfacenumvertices = surface->num_vertices;
8434 if (surface->lightmapinfo->samples)
8436 for (j = 0;j < surfacenumvertices;j++)
8438 lm = surface->lightmapinfo->samples + offsets[j];
8439 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8440 VectorScale(lm, scale, c);
8441 if (surface->lightmapinfo->styles[1] != 255)
8443 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8445 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8446 VectorMA(c, scale, lm, c);
8447 if (surface->lightmapinfo->styles[2] != 255)
8450 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8451 VectorMA(c, scale, lm, c);
8452 if (surface->lightmapinfo->styles[3] != 255)
8455 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8456 VectorMA(c, scale, lm, c);
8463 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);
8469 for (j = 0;j < surfacenumvertices;j++)
8471 Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8478 // if vertices are deformed (sprite flares and things in maps, possibly
8479 // water waves, bulges and other deformations), modify the copied vertices
8481 for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
8483 switch (deform->deform)
8486 case Q3DEFORM_PROJECTIONSHADOW:
8487 case Q3DEFORM_TEXT0:
8488 case Q3DEFORM_TEXT1:
8489 case Q3DEFORM_TEXT2:
8490 case Q3DEFORM_TEXT3:
8491 case Q3DEFORM_TEXT4:
8492 case Q3DEFORM_TEXT5:
8493 case Q3DEFORM_TEXT6:
8494 case Q3DEFORM_TEXT7:
8497 case Q3DEFORM_AUTOSPRITE:
8498 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8499 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8500 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8501 VectorNormalize(newforward);
8502 VectorNormalize(newright);
8503 VectorNormalize(newup);
8504 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8505 // rsurface.batchvertex3f_vertexbuffer = NULL;
8506 // rsurface.batchvertex3f_bufferoffset = 0;
8507 // rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8508 // rsurface.batchsvector3f_vertexbuffer = NULL;
8509 // rsurface.batchsvector3f_bufferoffset = 0;
8510 // rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8511 // rsurface.batchtvector3f_vertexbuffer = NULL;
8512 // rsurface.batchtvector3f_bufferoffset = 0;
8513 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8514 // rsurface.batchnormal3f_vertexbuffer = NULL;
8515 // rsurface.batchnormal3f_bufferoffset = 0;
8516 // a single autosprite surface can contain multiple sprites...
8517 for (j = 0;j < batchnumvertices - 3;j += 4)
8519 VectorClear(center);
8520 for (i = 0;i < 4;i++)
8521 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8522 VectorScale(center, 0.25f, center);
8523 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8524 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8525 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8526 for (i = 0;i < 4;i++)
8528 VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8529 VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8532 // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8533 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8534 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);
8536 case Q3DEFORM_AUTOSPRITE2:
8537 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8538 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8539 Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8540 VectorNormalize(newforward);
8541 VectorNormalize(newright);
8542 VectorNormalize(newup);
8543 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8544 // rsurface.batchvertex3f_vertexbuffer = NULL;
8545 // rsurface.batchvertex3f_bufferoffset = 0;
8547 const float *v1, *v2;
8557 memset(shortest, 0, sizeof(shortest));
8558 // a single autosprite surface can contain multiple sprites...
8559 for (j = 0;j < batchnumvertices - 3;j += 4)
8561 VectorClear(center);
8562 for (i = 0;i < 4;i++)
8563 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8564 VectorScale(center, 0.25f, center);
8565 // find the two shortest edges, then use them to define the
8566 // axis vectors for rotating around the central axis
8567 for (i = 0;i < 6;i++)
8569 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8570 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8571 l = VectorDistance2(v1, v2);
8572 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8574 l += (1.0f / 1024.0f);
8575 if (shortest[0].length2 > l || i == 0)
8577 shortest[1] = shortest[0];
8578 shortest[0].length2 = l;
8579 shortest[0].v1 = v1;
8580 shortest[0].v2 = v2;
8582 else if (shortest[1].length2 > l || i == 1)
8584 shortest[1].length2 = l;
8585 shortest[1].v1 = v1;
8586 shortest[1].v2 = v2;
8589 VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8590 VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8591 // this calculates the right vector from the shortest edge
8592 // and the up vector from the edge midpoints
8593 VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8594 VectorNormalize(right);
8595 VectorSubtract(end, start, up);
8596 VectorNormalize(up);
8597 // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8598 VectorSubtract(rsurface.localvieworigin, center, forward);
8599 //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8600 VectorNegate(forward, forward);
8601 VectorReflect(forward, 0, up, forward);
8602 VectorNormalize(forward);
8603 CrossProduct(up, forward, newright);
8604 VectorNormalize(newright);
8605 // rotate the quad around the up axis vector, this is made
8606 // especially easy by the fact we know the quad is flat,
8607 // so we only have to subtract the center position and
8608 // measure distance along the right vector, and then
8609 // multiply that by the newright vector and add back the
8611 // we also need to subtract the old position to undo the
8612 // displacement from the center, which we do with a
8613 // DotProduct, the subtraction/addition of center is also
8614 // optimized into DotProducts here
8615 l = DotProduct(right, center);
8616 for (i = 0;i < 4;i++)
8618 v1 = rsurface.batchvertex3f + 3*(j+i);
8619 f = DotProduct(right, v1) - l;
8620 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8624 if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8626 // rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8627 // rsurface.batchnormal3f_vertexbuffer = NULL;
8628 // rsurface.batchnormal3f_bufferoffset = 0;
8629 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8631 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8633 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8634 // rsurface.batchsvector3f_vertexbuffer = NULL;
8635 // rsurface.batchsvector3f_bufferoffset = 0;
8636 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8637 // rsurface.batchtvector3f_vertexbuffer = NULL;
8638 // rsurface.batchtvector3f_bufferoffset = 0;
8639 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);
8642 case Q3DEFORM_NORMAL:
8643 // deform the normals to make reflections wavey
8644 rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8645 rsurface.batchnormal3f_vertexbuffer = NULL;
8646 rsurface.batchnormal3f_bufferoffset = 0;
8647 for (j = 0;j < batchnumvertices;j++)
8650 float *normal = rsurface.batchnormal3f + 3*j;
8651 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
8652 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f( vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
8653 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]);
8654 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]);
8655 VectorNormalize(normal);
8657 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8659 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8660 // rsurface.batchsvector3f_vertexbuffer = NULL;
8661 // rsurface.batchsvector3f_bufferoffset = 0;
8662 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8663 // rsurface.batchtvector3f_vertexbuffer = NULL;
8664 // rsurface.batchtvector3f_bufferoffset = 0;
8665 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);
8669 // deform vertex array to make wavey water and flags and such
8670 waveparms[0] = deform->waveparms[0];
8671 waveparms[1] = deform->waveparms[1];
8672 waveparms[2] = deform->waveparms[2];
8673 waveparms[3] = deform->waveparms[3];
8674 if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
8675 break; // if wavefunc is a nop, don't make a dynamic vertex array
8676 // this is how a divisor of vertex influence on deformation
8677 animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
8678 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8679 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8680 // rsurface.batchvertex3f_vertexbuffer = NULL;
8681 // rsurface.batchvertex3f_bufferoffset = 0;
8682 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8683 // rsurface.batchnormal3f_vertexbuffer = NULL;
8684 // rsurface.batchnormal3f_bufferoffset = 0;
8685 for (j = 0;j < batchnumvertices;j++)
8687 // if the wavefunc depends on time, evaluate it per-vertex
8690 waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
8691 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
8693 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8695 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8696 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8697 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8699 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8700 // rsurface.batchsvector3f_vertexbuffer = NULL;
8701 // rsurface.batchsvector3f_bufferoffset = 0;
8702 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8703 // rsurface.batchtvector3f_vertexbuffer = NULL;
8704 // rsurface.batchtvector3f_bufferoffset = 0;
8705 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
8708 case Q3DEFORM_BULGE:
8709 // deform vertex array to make the surface have moving bulges
8710 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8711 // rsurface.batchvertex3f_vertexbuffer = NULL;
8712 // rsurface.batchvertex3f_bufferoffset = 0;
8713 // rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8714 // rsurface.batchnormal3f_vertexbuffer = NULL;
8715 // rsurface.batchnormal3f_bufferoffset = 0;
8716 for (j = 0;j < batchnumvertices;j++)
8718 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
8719 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
8721 // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
8722 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8723 if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8725 // rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8726 // rsurface.batchsvector3f_vertexbuffer = NULL;
8727 // rsurface.batchsvector3f_bufferoffset = 0;
8728 // rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8729 // rsurface.batchtvector3f_vertexbuffer = NULL;
8730 // rsurface.batchtvector3f_bufferoffset = 0;
8731 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);
8735 // deform vertex array
8736 if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8737 break; // if wavefunc is a nop, don't make a dynamic vertex array
8738 scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
8739 VectorScale(deform->parms, scale, waveparms);
8740 // rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8741 // rsurface.batchvertex3f_vertexbuffer = NULL;
8742 // rsurface.batchvertex3f_bufferoffset = 0;
8743 for (j = 0;j < batchnumvertices;j++)
8744 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
8749 // generate texcoords based on the chosen texcoord source
8750 switch(rsurface.texture->tcgen.tcgen)
8753 case Q3TCGEN_TEXTURE:
8755 case Q3TCGEN_LIGHTMAP:
8756 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8757 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8758 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8759 if (rsurface.batchtexcoordlightmap2f)
8760 memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
8762 case Q3TCGEN_VECTOR:
8763 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8764 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8765 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8766 for (j = 0;j < batchnumvertices;j++)
8768 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
8769 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
8772 case Q3TCGEN_ENVIRONMENT:
8773 // make environment reflections using a spheremap
8774 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8775 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8776 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8777 for (j = 0;j < batchnumvertices;j++)
8779 // identical to Q3A's method, but executed in worldspace so
8780 // carried models can be shiny too
8782 float viewer[3], d, reflected[3], worldreflected[3];
8784 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
8785 // VectorNormalize(viewer);
8787 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
8789 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
8790 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
8791 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
8792 // note: this is proportinal to viewer, so we can normalize later
8794 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
8795 VectorNormalize(worldreflected);
8797 // note: this sphere map only uses world x and z!
8798 // so positive and negative y will LOOK THE SAME.
8799 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
8800 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
8804 // the only tcmod that needs software vertex processing is turbulent, so
8805 // check for it here and apply the changes if needed
8806 // and we only support that as the first one
8807 // (handling a mixture of turbulent and other tcmods would be problematic
8808 // without punting it entirely to a software path)
8809 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8811 amplitude = rsurface.texture->tcmods[0].parms[1];
8812 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
8813 // rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8814 // rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8815 // rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8816 for (j = 0;j < batchnumvertices;j++)
8818 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);
8819 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1] ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
8823 if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8825 // convert the modified arrays to vertex structs
8826 // rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8827 // rsurface.batchvertexmeshbuffer = NULL;
8828 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
8829 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8830 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
8831 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
8832 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8833 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
8834 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
8836 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8838 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
8839 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
8842 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
8843 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8844 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
8845 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
8846 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8847 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
8848 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
8849 for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
8850 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
8854 void RSurf_DrawBatch(void)
8856 // sometimes a zero triangle surface (usually a degenerate patch) makes it
8857 // through the pipeline, killing it earlier in the pipeline would have
8858 // per-surface overhead rather than per-batch overhead, so it's best to
8859 // reject it here, before it hits glDraw.
8860 if (rsurface.batchnumtriangles == 0)
8863 // batch debugging code
8864 if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
8870 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
8871 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
8874 for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
8876 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
8878 if (rsurface.modelsurfaces[j].texture != rsurface.texture)
8879 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);
8886 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);
8889 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
8891 // pick the closest matching water plane
8892 int planeindex, vertexindex, bestplaneindex = -1;
8896 r_waterstate_waterplane_t *p;
8897 qboolean prepared = false;
8899 for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8901 if(p->camera_entity != rsurface.texture->camera_entity)
8906 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
8908 if(rsurface.batchnumvertices == 0)
8911 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
8913 Matrix4x4_Transform(&rsurface.matrix, v, vert);
8914 d += fabs(PlaneDiff(vert, &p->plane));
8916 if (bestd > d || bestplaneindex < 0)
8919 bestplaneindex = planeindex;
8922 return bestplaneindex;
8923 // NOTE: this MAY return a totally unrelated water plane; we can ignore
8924 // this situation though, as it might be better to render single larger
8925 // batches with useless stuff (backface culled for example) than to
8926 // render multiple smaller batches
8929 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
8932 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8933 rsurface.passcolor4f_vertexbuffer = 0;
8934 rsurface.passcolor4f_bufferoffset = 0;
8935 for (i = 0;i < rsurface.batchnumvertices;i++)
8936 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
8939 static void RSurf_DrawBatch_GL11_ApplyFog(void)
8946 if (rsurface.passcolor4f)
8948 // generate color arrays
8949 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8950 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8951 rsurface.passcolor4f_vertexbuffer = 0;
8952 rsurface.passcolor4f_bufferoffset = 0;
8953 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)
8955 f = RSurf_FogVertex(v);
8964 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8965 rsurface.passcolor4f_vertexbuffer = 0;
8966 rsurface.passcolor4f_bufferoffset = 0;
8967 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
8969 f = RSurf_FogVertex(v);
8978 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
8985 if (!rsurface.passcolor4f)
8987 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
8988 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
8989 rsurface.passcolor4f_vertexbuffer = 0;
8990 rsurface.passcolor4f_bufferoffset = 0;
8991 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)
8993 f = RSurf_FogVertex(v);
8994 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
8995 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
8996 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9001 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9006 if (!rsurface.passcolor4f)
9008 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9009 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9010 rsurface.passcolor4f_vertexbuffer = 0;
9011 rsurface.passcolor4f_bufferoffset = 0;
9012 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9021 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9026 if (!rsurface.passcolor4f)
9028 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9029 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9030 rsurface.passcolor4f_vertexbuffer = 0;
9031 rsurface.passcolor4f_bufferoffset = 0;
9032 for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9034 c2[0] = c[0] + r_refdef.scene.ambient;
9035 c2[1] = c[1] + r_refdef.scene.ambient;
9036 c2[2] = c[2] + r_refdef.scene.ambient;
9041 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9044 rsurface.passcolor4f = NULL;
9045 rsurface.passcolor4f_vertexbuffer = 0;
9046 rsurface.passcolor4f_bufferoffset = 0;
9047 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9048 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9049 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9050 GL_Color(r, g, b, a);
9051 R_Mesh_TexBind(0, rsurface.lightmaptexture);
9055 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9057 // TODO: optimize applyfog && applycolor case
9058 // just apply fog if necessary, and tint the fog color array if necessary
9059 rsurface.passcolor4f = NULL;
9060 rsurface.passcolor4f_vertexbuffer = 0;
9061 rsurface.passcolor4f_bufferoffset = 0;
9062 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9063 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9064 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9065 GL_Color(r, g, b, a);
9069 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9072 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9073 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9074 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9075 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9076 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9077 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9078 GL_Color(r, g, b, a);
9082 static void RSurf_DrawBatch_GL11_ClampColor(void)
9087 if (!rsurface.passcolor4f)
9089 for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9091 c2[0] = bound(0.0f, c1[0], 1.0f);
9092 c2[1] = bound(0.0f, c1[1], 1.0f);
9093 c2[2] = bound(0.0f, c1[2], 1.0f);
9094 c2[3] = bound(0.0f, c1[3], 1.0f);
9098 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9108 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9109 rsurface.passcolor4f_vertexbuffer = 0;
9110 rsurface.passcolor4f_bufferoffset = 0;
9111 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)
9113 f = -DotProduct(r_refdef.view.forward, n);
9115 f = f * 0.85 + 0.15; // work around so stuff won't get black
9116 f *= r_refdef.lightmapintensity;
9117 Vector4Set(c, f, f, f, 1);
9121 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9123 RSurf_DrawBatch_GL11_ApplyFakeLight();
9124 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9125 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9126 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9127 GL_Color(r, g, b, a);
9131 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9139 vec3_t ambientcolor;
9140 vec3_t diffusecolor;
9144 VectorCopy(rsurface.modellight_lightdir, lightdir);
9145 f = 0.5f * r_refdef.lightmapintensity;
9146 ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9147 ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9148 ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9149 diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9150 diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9151 diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9153 if (VectorLength2(diffusecolor) > 0)
9155 // q3-style directional shading
9156 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9157 rsurface.passcolor4f_vertexbuffer = 0;
9158 rsurface.passcolor4f_bufferoffset = 0;
9159 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)
9161 if ((f = DotProduct(n, lightdir)) > 0)
9162 VectorMA(ambientcolor, f, diffusecolor, c);
9164 VectorCopy(ambientcolor, c);
9171 *applycolor = false;
9175 *r = ambientcolor[0];
9176 *g = ambientcolor[1];
9177 *b = ambientcolor[2];
9178 rsurface.passcolor4f = NULL;
9179 rsurface.passcolor4f_vertexbuffer = 0;
9180 rsurface.passcolor4f_bufferoffset = 0;
9184 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9186 RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9187 if (applyfog) RSurf_DrawBatch_GL11_ApplyFog();
9188 if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9189 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9190 GL_Color(r, g, b, a);
9194 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9200 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9202 f = 1 - RSurf_FogVertex(v);
9210 void RSurf_SetupDepthAndCulling(void)
9212 // submodels are biased to avoid z-fighting with world surfaces that they
9213 // may be exactly overlapping (avoids z-fighting artifacts on certain
9214 // doors and things in Quake maps)
9215 GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9216 GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9217 GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9218 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9221 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9223 // transparent sky would be ridiculous
9224 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9226 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9227 skyrenderlater = true;
9228 RSurf_SetupDepthAndCulling();
9230 // LordHavoc: HalfLife maps have freaky skypolys so don't use
9231 // skymasking on them, and Quake3 never did sky masking (unlike
9232 // software Quake and software Quake2), so disable the sky masking
9233 // in Quake3 maps as it causes problems with q3map2 sky tricks,
9234 // and skymasking also looks very bad when noclipping outside the
9235 // level, so don't use it then either.
9236 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
9238 R_Mesh_ResetTextureState();
9239 if (skyrendermasked)
9241 R_SetupShader_DepthOrShadow();
9242 // depth-only (masking)
9243 GL_ColorMask(0,0,0,0);
9244 // just to make sure that braindead drivers don't draw
9245 // anything despite that colormask...
9246 GL_BlendFunc(GL_ZERO, GL_ONE);
9247 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9248 if (rsurface.batchvertex3fbuffer)
9249 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9251 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9255 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9257 GL_BlendFunc(GL_ONE, GL_ZERO);
9258 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9259 GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9260 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9263 if (skyrendermasked)
9264 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9266 R_Mesh_ResetTextureState();
9267 GL_Color(1, 1, 1, 1);
9270 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9271 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9272 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9274 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9278 // render screenspace normalmap to texture
9280 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
9285 // bind lightmap texture
9287 // water/refraction/reflection/camera surfaces have to be handled specially
9288 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9290 int start, end, startplaneindex;
9291 for (start = 0;start < texturenumsurfaces;start = end)
9293 startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9294 if(startplaneindex < 0)
9296 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9297 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9301 for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9303 // now that we have a batch using the same planeindex, render it
9304 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9306 // render water or distortion background
9308 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));
9310 // blend surface on top
9311 GL_DepthMask(false);
9312 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
9315 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9317 // render surface with reflection texture as input
9318 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9319 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));
9326 // render surface batch normally
9327 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9328 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
9332 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9334 // OpenGL 1.3 path - anything not completely ancient
9335 qboolean applycolor;
9338 const texturelayer_t *layer;
9339 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);
9340 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9342 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9345 int layertexrgbscale;
9346 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9348 if (layerindex == 0)
9352 GL_AlphaTest(false);
9353 GL_DepthFunc(GL_EQUAL);
9356 GL_DepthMask(layer->depthmask && writedepth);
9357 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9358 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9360 layertexrgbscale = 4;
9361 VectorScale(layer->color, 0.25f, layercolor);
9363 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9365 layertexrgbscale = 2;
9366 VectorScale(layer->color, 0.5f, layercolor);
9370 layertexrgbscale = 1;
9371 VectorScale(layer->color, 1.0f, layercolor);
9373 layercolor[3] = layer->color[3];
9374 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9375 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9376 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9377 switch (layer->type)
9379 case TEXTURELAYERTYPE_LITTEXTURE:
9380 // single-pass lightmapped texture with 2x rgbscale
9381 R_Mesh_TexBind(0, r_texture_white);
9382 R_Mesh_TexMatrix(0, NULL);
9383 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9384 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9385 R_Mesh_TexBind(1, layer->texture);
9386 R_Mesh_TexMatrix(1, &layer->texmatrix);
9387 R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9388 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9389 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9390 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9391 else if (FAKELIGHT_ENABLED)
9392 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9393 else if (rsurface.uselightmaptexture)
9394 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9396 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9398 case TEXTURELAYERTYPE_TEXTURE:
9399 // singletexture unlit texture with transparency support
9400 R_Mesh_TexBind(0, layer->texture);
9401 R_Mesh_TexMatrix(0, &layer->texmatrix);
9402 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9403 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9404 R_Mesh_TexBind(1, 0);
9405 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9406 RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9408 case TEXTURELAYERTYPE_FOG:
9409 // singletexture fogging
9412 R_Mesh_TexBind(0, layer->texture);
9413 R_Mesh_TexMatrix(0, &layer->texmatrix);
9414 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9415 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9419 R_Mesh_TexBind(0, 0);
9420 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9422 R_Mesh_TexBind(1, 0);
9423 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9424 // generate a color array for the fog pass
9425 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9426 RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9430 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9433 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9435 GL_DepthFunc(GL_LEQUAL);
9436 GL_AlphaTest(false);
9440 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9442 // OpenGL 1.1 - crusty old voodoo path
9445 const texturelayer_t *layer;
9446 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);
9447 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9449 for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9451 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9453 if (layerindex == 0)
9457 GL_AlphaTest(false);
9458 GL_DepthFunc(GL_EQUAL);
9461 GL_DepthMask(layer->depthmask && writedepth);
9462 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9463 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9464 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9465 switch (layer->type)
9467 case TEXTURELAYERTYPE_LITTEXTURE:
9468 if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9470 // two-pass lit texture with 2x rgbscale
9471 // first the lightmap pass
9472 R_Mesh_TexBind(0, r_texture_white);
9473 R_Mesh_TexMatrix(0, NULL);
9474 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9475 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9476 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9477 RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9478 else if (FAKELIGHT_ENABLED)
9479 RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9480 else if (rsurface.uselightmaptexture)
9481 RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9483 RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9484 // then apply the texture to it
9485 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9486 R_Mesh_TexBind(0, layer->texture);
9487 R_Mesh_TexMatrix(0, &layer->texmatrix);
9488 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9489 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9490 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);
9494 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9495 R_Mesh_TexBind(0, layer->texture);
9496 R_Mesh_TexMatrix(0, &layer->texmatrix);
9497 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9498 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9499 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9500 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);
9502 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);
9505 case TEXTURELAYERTYPE_TEXTURE:
9506 // singletexture unlit texture with transparency support
9507 R_Mesh_TexBind(0, layer->texture);
9508 R_Mesh_TexMatrix(0, &layer->texmatrix);
9509 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9510 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9511 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);
9513 case TEXTURELAYERTYPE_FOG:
9514 // singletexture fogging
9517 R_Mesh_TexBind(0, layer->texture);
9518 R_Mesh_TexMatrix(0, &layer->texmatrix);
9519 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9520 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9524 R_Mesh_TexBind(0, 0);
9525 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9527 // generate a color array for the fog pass
9528 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9529 RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9533 Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9536 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9538 GL_DepthFunc(GL_LEQUAL);
9539 GL_AlphaTest(false);
9543 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9547 r_vertexgeneric_t *batchvertex;
9550 // R_Mesh_ResetTextureState();
9551 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9553 if(rsurface.texture && rsurface.texture->currentskinframe)
9555 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9556 c[3] *= rsurface.texture->currentalpha;
9566 if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9568 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9569 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9570 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9573 // brighten it up (as texture value 127 means "unlit")
9574 c[0] *= 2 * r_refdef.view.colorscale;
9575 c[1] *= 2 * r_refdef.view.colorscale;
9576 c[2] *= 2 * r_refdef.view.colorscale;
9578 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9579 c[3] *= r_wateralpha.value;
9581 if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9583 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9584 GL_DepthMask(false);
9586 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9588 GL_BlendFunc(GL_ONE, GL_ONE);
9589 GL_DepthMask(false);
9591 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9593 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9594 GL_DepthMask(false);
9596 else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9598 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9599 GL_DepthMask(false);
9603 GL_BlendFunc(GL_ONE, GL_ZERO);
9604 GL_DepthMask(writedepth);
9607 if (r_showsurfaces.integer == 3)
9609 rsurface.passcolor4f = NULL;
9611 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9613 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9615 rsurface.passcolor4f = NULL;
9616 rsurface.passcolor4f_vertexbuffer = 0;
9617 rsurface.passcolor4f_bufferoffset = 0;
9619 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9621 qboolean applycolor = true;
9624 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9626 r_refdef.lightmapintensity = 1;
9627 RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9628 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9630 else if (FAKELIGHT_ENABLED)
9632 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9634 r_refdef.lightmapintensity = r_fakelight_intensity.value;
9635 RSurf_DrawBatch_GL11_ApplyFakeLight();
9636 r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9640 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9642 rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9643 rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9644 rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9647 if(!rsurface.passcolor4f)
9648 RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
9650 RSurf_DrawBatch_GL11_ApplyAmbient();
9651 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
9652 if(r_refdef.fogenabled)
9653 RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
9654 RSurf_DrawBatch_GL11_ClampColor();
9656 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
9657 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9660 else if (!r_refdef.view.showdebug)
9662 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9663 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9664 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9666 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9667 Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
9669 R_Mesh_PrepareVertices_Generic_Unlock();
9672 else if (r_showsurfaces.integer == 4)
9674 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9675 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
9676 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
9678 unsigned char c = (vi << 3) * (1.0f / 256.0f);
9679 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9680 Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
9682 R_Mesh_PrepareVertices_Generic_Unlock();
9685 else if (r_showsurfaces.integer == 2)
9688 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9689 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
9690 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
9692 unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
9693 VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
9694 VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
9695 VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
9696 Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
9697 Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
9698 Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
9700 R_Mesh_PrepareVertices_Generic_Unlock();
9701 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
9705 int texturesurfaceindex;
9707 const msurface_t *surface;
9708 float surfacecolor4f[4];
9709 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9710 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
9712 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
9714 surface = texturesurfacelist[texturesurfaceindex];
9715 k = (int)(((size_t)surface) / sizeof(msurface_t));
9716 Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
9717 for (j = 0;j < surface->num_vertices;j++)
9719 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
9720 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
9724 R_Mesh_PrepareVertices_Generic_Unlock();
9729 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9732 RSurf_SetupDepthAndCulling();
9733 if (r_showsurfaces.integer)
9735 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9738 switch (vid.renderpath)
9740 case RENDERPATH_GL20:
9741 case RENDERPATH_D3D9:
9742 case RENDERPATH_D3D10:
9743 case RENDERPATH_D3D11:
9744 case RENDERPATH_SOFT:
9745 case RENDERPATH_GLES2:
9746 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9748 case RENDERPATH_GL13:
9749 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9751 case RENDERPATH_GL11:
9752 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9758 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9761 RSurf_SetupDepthAndCulling();
9762 if (r_showsurfaces.integer)
9764 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
9767 switch (vid.renderpath)
9769 case RENDERPATH_GL20:
9770 case RENDERPATH_D3D9:
9771 case RENDERPATH_D3D10:
9772 case RENDERPATH_D3D11:
9773 case RENDERPATH_SOFT:
9774 case RENDERPATH_GLES2:
9775 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9777 case RENDERPATH_GL13:
9778 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
9780 case RENDERPATH_GL11:
9781 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
9787 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9790 int texturenumsurfaces, endsurface;
9792 const msurface_t *surface;
9793 #define MAXBATCH_TRANSPARENTSURFACES 256
9794 const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
9796 // if the model is static it doesn't matter what value we give for
9797 // wantnormals and wanttangents, so this logic uses only rules applicable
9798 // to a model, knowing that they are meaningless otherwise
9799 if (ent == r_refdef.scene.worldentity)
9800 RSurf_ActiveWorldEntity();
9801 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
9802 RSurf_ActiveModelEntity(ent, false, false, false);
9805 switch (vid.renderpath)
9807 case RENDERPATH_GL20:
9808 case RENDERPATH_D3D9:
9809 case RENDERPATH_D3D10:
9810 case RENDERPATH_D3D11:
9811 case RENDERPATH_SOFT:
9812 case RENDERPATH_GLES2:
9813 RSurf_ActiveModelEntity(ent, true, true, false);
9815 case RENDERPATH_GL13:
9816 case RENDERPATH_GL11:
9817 RSurf_ActiveModelEntity(ent, true, false, false);
9822 if (r_transparentdepthmasking.integer)
9824 qboolean setup = false;
9825 for (i = 0;i < numsurfaces;i = j)
9828 surface = rsurface.modelsurfaces + surfacelist[i];
9829 texture = surface->texture;
9830 rsurface.texture = R_GetCurrentTexture(texture);
9831 rsurface.lightmaptexture = NULL;
9832 rsurface.deluxemaptexture = NULL;
9833 rsurface.uselightmaptexture = false;
9834 // scan ahead until we find a different texture
9835 endsurface = min(i + 1024, numsurfaces);
9836 texturenumsurfaces = 0;
9837 texturesurfacelist[texturenumsurfaces++] = surface;
9838 for (;j < endsurface;j++)
9840 surface = rsurface.modelsurfaces + surfacelist[j];
9841 if (texture != surface->texture)
9843 texturesurfacelist[texturenumsurfaces++] = surface;
9845 if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
9847 // render the range of surfaces as depth
9851 GL_ColorMask(0,0,0,0);
9854 GL_BlendFunc(GL_ONE, GL_ZERO);
9856 // R_Mesh_ResetTextureState();
9857 R_SetupShader_DepthOrShadow();
9859 RSurf_SetupDepthAndCulling();
9860 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9861 if (rsurface.batchvertex3fbuffer)
9862 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9864 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9868 GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9871 for (i = 0;i < numsurfaces;i = j)
9874 surface = rsurface.modelsurfaces + surfacelist[i];
9875 texture = surface->texture;
9876 rsurface.texture = R_GetCurrentTexture(texture);
9877 // scan ahead until we find a different texture
9878 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
9879 texturenumsurfaces = 0;
9880 texturesurfacelist[texturenumsurfaces++] = surface;
9881 if(FAKELIGHT_ENABLED)
9883 rsurface.lightmaptexture = NULL;
9884 rsurface.deluxemaptexture = NULL;
9885 rsurface.uselightmaptexture = false;
9886 for (;j < endsurface;j++)
9888 surface = rsurface.modelsurfaces + surfacelist[j];
9889 if (texture != surface->texture)
9891 texturesurfacelist[texturenumsurfaces++] = surface;
9896 rsurface.lightmaptexture = surface->lightmaptexture;
9897 rsurface.deluxemaptexture = surface->deluxemaptexture;
9898 rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
9899 for (;j < endsurface;j++)
9901 surface = rsurface.modelsurfaces + surfacelist[j];
9902 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
9904 texturesurfacelist[texturenumsurfaces++] = surface;
9907 // render the range of surfaces
9908 if (ent == r_refdef.scene.worldentity)
9909 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9911 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
9913 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9916 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
9918 // transparent surfaces get pushed off into the transparent queue
9919 int surfacelistindex;
9920 const msurface_t *surface;
9921 vec3_t tempcenter, center;
9922 for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
9924 surface = texturesurfacelist[surfacelistindex];
9925 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
9926 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
9927 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
9928 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
9929 if (queueentity->transparent_offset) // transparent offset
9931 center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
9932 center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
9933 center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
9935 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
9939 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9941 if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
9943 if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
9945 RSurf_SetupDepthAndCulling();
9946 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
9947 if (rsurface.batchvertex3fbuffer)
9948 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9950 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9954 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
9956 const entity_render_t *queueentity = r_refdef.scene.worldentity;
9959 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
9962 if (!rsurface.texture->currentnumlayers)
9964 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9965 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9967 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
9969 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
9970 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
9971 else if (!rsurface.texture->currentnumlayers)
9973 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
9975 // in the deferred case, transparent surfaces were queued during prepass
9976 if (!r_shadow_usingdeferredprepass)
9977 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
9981 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
9982 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
9987 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
9991 R_FrameData_SetMark();
9992 // break the surface list down into batches by texture and use of lightmapping
9993 for (i = 0;i < numsurfaces;i = j)
9996 // texture is the base texture pointer, rsurface.texture is the
9997 // current frame/skin the texture is directing us to use (for example
9998 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
9999 // use skin 1 instead)
10000 texture = surfacelist[i]->texture;
10001 rsurface.texture = R_GetCurrentTexture(texture);
10002 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10004 // if this texture is not the kind we want, skip ahead to the next one
10005 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10009 if(FAKELIGHT_ENABLED || depthonly || prepass)
10011 rsurface.lightmaptexture = NULL;
10012 rsurface.deluxemaptexture = NULL;
10013 rsurface.uselightmaptexture = false;
10014 // simply scan ahead until we find a different texture or lightmap state
10015 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10020 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10021 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10022 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10023 // simply scan ahead until we find a different texture or lightmap state
10024 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10027 // render the range of surfaces
10028 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10030 R_FrameData_ReturnToMark();
10033 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10037 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10040 if (!rsurface.texture->currentnumlayers)
10042 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10043 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10045 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10047 else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
10048 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10049 else if (!rsurface.texture->currentnumlayers)
10051 else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10053 // in the deferred case, transparent surfaces were queued during prepass
10054 if (!r_shadow_usingdeferredprepass)
10055 R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10059 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10060 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10065 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10068 texture_t *texture;
10069 R_FrameData_SetMark();
10070 // break the surface list down into batches by texture and use of lightmapping
10071 for (i = 0;i < numsurfaces;i = j)
10074 // texture is the base texture pointer, rsurface.texture is the
10075 // current frame/skin the texture is directing us to use (for example
10076 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10077 // use skin 1 instead)
10078 texture = surfacelist[i]->texture;
10079 rsurface.texture = R_GetCurrentTexture(texture);
10080 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10082 // if this texture is not the kind we want, skip ahead to the next one
10083 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10087 if(FAKELIGHT_ENABLED || depthonly || prepass)
10089 rsurface.lightmaptexture = NULL;
10090 rsurface.deluxemaptexture = NULL;
10091 rsurface.uselightmaptexture = false;
10092 // simply scan ahead until we find a different texture or lightmap state
10093 for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10098 rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10099 rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10100 rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10101 // simply scan ahead until we find a different texture or lightmap state
10102 for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10105 // render the range of surfaces
10106 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10108 R_FrameData_ReturnToMark();
10111 float locboxvertex3f[6*4*3] =
10113 1,0,1, 1,0,0, 1,1,0, 1,1,1,
10114 0,1,1, 0,1,0, 0,0,0, 0,0,1,
10115 1,1,1, 1,1,0, 0,1,0, 0,1,1,
10116 0,0,1, 0,0,0, 1,0,0, 1,0,1,
10117 0,0,1, 1,0,1, 1,1,1, 0,1,1,
10118 1,0,0, 0,0,0, 0,1,0, 1,1,0
10121 unsigned short locboxelements[6*2*3] =
10126 12,13,14, 12,14,15,
10127 16,17,18, 16,18,19,
10131 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10134 cl_locnode_t *loc = (cl_locnode_t *)ent;
10136 float vertex3f[6*4*3];
10138 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10139 GL_DepthMask(false);
10140 GL_DepthRange(0, 1);
10141 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10142 GL_DepthTest(true);
10143 GL_CullFace(GL_NONE);
10144 R_EntityMatrix(&identitymatrix);
10146 // R_Mesh_ResetTextureState();
10148 i = surfacelist[0];
10149 GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10150 ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10151 ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10152 surfacelist[0] < 0 ? 0.5f : 0.125f);
10154 if (VectorCompare(loc->mins, loc->maxs))
10156 VectorSet(size, 2, 2, 2);
10157 VectorMA(loc->mins, -0.5f, size, mins);
10161 VectorCopy(loc->mins, mins);
10162 VectorSubtract(loc->maxs, loc->mins, size);
10165 for (i = 0;i < 6*4*3;)
10166 for (j = 0;j < 3;j++, i++)
10167 vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10169 R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10170 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10171 R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10174 void R_DrawLocs(void)
10177 cl_locnode_t *loc, *nearestloc;
10179 nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10180 for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10182 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10183 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10187 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10189 if (decalsystem->decals)
10190 Mem_Free(decalsystem->decals);
10191 memset(decalsystem, 0, sizeof(*decalsystem));
10194 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)
10197 tridecal_t *decals;
10200 // expand or initialize the system
10201 if (decalsystem->maxdecals <= decalsystem->numdecals)
10203 decalsystem_t old = *decalsystem;
10204 qboolean useshortelements;
10205 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10206 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10207 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)));
10208 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10209 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10210 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10211 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10212 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10213 if (decalsystem->numdecals)
10214 memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10216 Mem_Free(old.decals);
10217 for (i = 0;i < decalsystem->maxdecals*3;i++)
10218 decalsystem->element3i[i] = i;
10219 if (useshortelements)
10220 for (i = 0;i < decalsystem->maxdecals*3;i++)
10221 decalsystem->element3s[i] = i;
10224 // grab a decal and search for another free slot for the next one
10225 decals = decalsystem->decals;
10226 decal = decalsystem->decals + (i = decalsystem->freedecal++);
10227 for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10229 decalsystem->freedecal = i;
10230 if (decalsystem->numdecals <= i)
10231 decalsystem->numdecals = i + 1;
10233 // initialize the decal
10235 decal->triangleindex = triangleindex;
10236 decal->surfaceindex = surfaceindex;
10237 decal->decalsequence = decalsequence;
10238 decal->color4f[0][0] = c0[0];
10239 decal->color4f[0][1] = c0[1];
10240 decal->color4f[0][2] = c0[2];
10241 decal->color4f[0][3] = 1;
10242 decal->color4f[1][0] = c1[0];
10243 decal->color4f[1][1] = c1[1];
10244 decal->color4f[1][2] = c1[2];
10245 decal->color4f[1][3] = 1;
10246 decal->color4f[2][0] = c2[0];
10247 decal->color4f[2][1] = c2[1];
10248 decal->color4f[2][2] = c2[2];
10249 decal->color4f[2][3] = 1;
10250 decal->vertex3f[0][0] = v0[0];
10251 decal->vertex3f[0][1] = v0[1];
10252 decal->vertex3f[0][2] = v0[2];
10253 decal->vertex3f[1][0] = v1[0];
10254 decal->vertex3f[1][1] = v1[1];
10255 decal->vertex3f[1][2] = v1[2];
10256 decal->vertex3f[2][0] = v2[0];
10257 decal->vertex3f[2][1] = v2[1];
10258 decal->vertex3f[2][2] = v2[2];
10259 decal->texcoord2f[0][0] = t0[0];
10260 decal->texcoord2f[0][1] = t0[1];
10261 decal->texcoord2f[1][0] = t1[0];
10262 decal->texcoord2f[1][1] = t1[1];
10263 decal->texcoord2f[2][0] = t2[0];
10264 decal->texcoord2f[2][1] = t2[1];
10267 extern cvar_t cl_decals_bias;
10268 extern cvar_t cl_decals_models;
10269 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10270 // baseparms, parms, temps
10271 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)
10276 const float *vertex3f;
10277 const float *normal3f;
10279 float points[2][9][3];
10286 e = rsurface.modelelement3i + 3*triangleindex;
10288 vertex3f = rsurface.modelvertex3f;
10289 normal3f = rsurface.modelnormal3f;
10293 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10295 index = 3*e[cornerindex];
10296 VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10301 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10303 index = 3*e[cornerindex];
10304 VectorCopy(vertex3f + index, v[cornerindex]);
10309 //TriangleNormal(v[0], v[1], v[2], normal);
10310 //if (DotProduct(normal, localnormal) < 0.0f)
10312 // clip by each of the box planes formed from the projection matrix
10313 // if anything survives, we emit the decal
10314 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]);
10317 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]);
10320 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]);
10323 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]);
10326 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]);
10329 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]);
10332 // some part of the triangle survived, so we have to accept it...
10335 // dynamic always uses the original triangle
10337 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10339 index = 3*e[cornerindex];
10340 VectorCopy(vertex3f + index, v[cornerindex]);
10343 for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10345 // convert vertex positions to texcoords
10346 Matrix4x4_Transform(projection, v[cornerindex], temp);
10347 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10348 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10349 // calculate distance fade from the projection origin
10350 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10351 f = bound(0.0f, f, 1.0f);
10352 c[cornerindex][0] = r * f;
10353 c[cornerindex][1] = g * f;
10354 c[cornerindex][2] = b * f;
10355 c[cornerindex][3] = 1.0f;
10356 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10359 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);
10361 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10362 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);
10364 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)
10366 matrix4x4_t projection;
10367 decalsystem_t *decalsystem;
10370 const msurface_t *surface;
10371 const msurface_t *surfaces;
10372 const int *surfacelist;
10373 const texture_t *texture;
10375 int numsurfacelist;
10376 int surfacelistindex;
10379 float localorigin[3];
10380 float localnormal[3];
10381 float localmins[3];
10382 float localmaxs[3];
10385 float planes[6][4];
10388 int bih_triangles_count;
10389 int bih_triangles[256];
10390 int bih_surfaces[256];
10392 decalsystem = &ent->decalsystem;
10393 model = ent->model;
10394 if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10396 R_DecalSystem_Reset(&ent->decalsystem);
10400 if (!model->brush.data_leafs && !cl_decals_models.integer)
10402 if (decalsystem->model)
10403 R_DecalSystem_Reset(decalsystem);
10407 if (decalsystem->model != model)
10408 R_DecalSystem_Reset(decalsystem);
10409 decalsystem->model = model;
10411 RSurf_ActiveModelEntity(ent, true, false, false);
10413 Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10414 Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10415 VectorNormalize(localnormal);
10416 localsize = worldsize*rsurface.inversematrixscale;
10417 localmins[0] = localorigin[0] - localsize;
10418 localmins[1] = localorigin[1] - localsize;
10419 localmins[2] = localorigin[2] - localsize;
10420 localmaxs[0] = localorigin[0] + localsize;
10421 localmaxs[1] = localorigin[1] + localsize;
10422 localmaxs[2] = localorigin[2] + localsize;
10424 //VectorCopy(localnormal, planes[4]);
10425 //VectorVectors(planes[4], planes[2], planes[0]);
10426 AnglesFromVectors(angles, localnormal, NULL, false);
10427 AngleVectors(angles, planes[0], planes[2], planes[4]);
10428 VectorNegate(planes[0], planes[1]);
10429 VectorNegate(planes[2], planes[3]);
10430 VectorNegate(planes[4], planes[5]);
10431 planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10432 planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10433 planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10434 planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10435 planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10436 planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10441 matrix4x4_t forwardprojection;
10442 Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10443 Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10448 float projectionvector[4][3];
10449 VectorScale(planes[0], ilocalsize, projectionvector[0]);
10450 VectorScale(planes[2], ilocalsize, projectionvector[1]);
10451 VectorScale(planes[4], ilocalsize, projectionvector[2]);
10452 projectionvector[0][0] = planes[0][0] * ilocalsize;
10453 projectionvector[0][1] = planes[1][0] * ilocalsize;
10454 projectionvector[0][2] = planes[2][0] * ilocalsize;
10455 projectionvector[1][0] = planes[0][1] * ilocalsize;
10456 projectionvector[1][1] = planes[1][1] * ilocalsize;
10457 projectionvector[1][2] = planes[2][1] * ilocalsize;
10458 projectionvector[2][0] = planes[0][2] * ilocalsize;
10459 projectionvector[2][1] = planes[1][2] * ilocalsize;
10460 projectionvector[2][2] = planes[2][2] * ilocalsize;
10461 projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10462 projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10463 projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10464 Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10468 dynamic = model->surfmesh.isanimated;
10469 numsurfacelist = model->nummodelsurfaces;
10470 surfacelist = model->sortedmodelsurfaces;
10471 surfaces = model->data_surfaces;
10474 bih_triangles_count = -1;
10477 if(model->render_bih.numleafs)
10478 bih = &model->render_bih;
10479 else if(model->collision_bih.numleafs)
10480 bih = &model->collision_bih;
10483 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10484 if(bih_triangles_count == 0)
10486 if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10488 if(bih_triangles_count > 0)
10490 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10492 surfaceindex = bih_surfaces[triangleindex];
10493 surface = surfaces + surfaceindex;
10494 texture = surface->texture;
10495 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10497 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10499 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10504 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10506 surfaceindex = surfacelist[surfacelistindex];
10507 surface = surfaces + surfaceindex;
10508 // check cull box first because it rejects more than any other check
10509 if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10511 // skip transparent surfaces
10512 texture = surface->texture;
10513 if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10515 if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10517 numtriangles = surface->num_triangles;
10518 for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10519 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10524 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10525 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)
10527 int renderentityindex;
10528 float worldmins[3];
10529 float worldmaxs[3];
10530 entity_render_t *ent;
10532 if (!cl_decals_newsystem.integer)
10535 worldmins[0] = worldorigin[0] - worldsize;
10536 worldmins[1] = worldorigin[1] - worldsize;
10537 worldmins[2] = worldorigin[2] - worldsize;
10538 worldmaxs[0] = worldorigin[0] + worldsize;
10539 worldmaxs[1] = worldorigin[1] + worldsize;
10540 worldmaxs[2] = worldorigin[2] + worldsize;
10542 R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10544 for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10546 ent = r_refdef.scene.entities[renderentityindex];
10547 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10550 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10554 typedef struct r_decalsystem_splatqueue_s
10556 vec3_t worldorigin;
10557 vec3_t worldnormal;
10563 r_decalsystem_splatqueue_t;
10565 int r_decalsystem_numqueued = 0;
10566 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10568 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)
10570 r_decalsystem_splatqueue_t *queue;
10572 if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10575 queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10576 VectorCopy(worldorigin, queue->worldorigin);
10577 VectorCopy(worldnormal, queue->worldnormal);
10578 Vector4Set(queue->color, r, g, b, a);
10579 Vector4Set(queue->tcrange, s1, t1, s2, t2);
10580 queue->worldsize = worldsize;
10581 queue->decalsequence = cl.decalsequence++;
10584 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10587 r_decalsystem_splatqueue_t *queue;
10589 for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10590 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);
10591 r_decalsystem_numqueued = 0;
10594 extern cvar_t cl_decals_max;
10595 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10598 decalsystem_t *decalsystem = &ent->decalsystem;
10605 if (!decalsystem->numdecals)
10608 if (r_showsurfaces.integer)
10611 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10613 R_DecalSystem_Reset(decalsystem);
10617 killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10618 lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10620 if (decalsystem->lastupdatetime)
10621 frametime = (cl.time - decalsystem->lastupdatetime);
10624 decalsystem->lastupdatetime = cl.time;
10625 decal = decalsystem->decals;
10626 numdecals = decalsystem->numdecals;
10628 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10630 if (decal->color4f[0][3])
10632 decal->lived += frametime;
10633 if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
10635 memset(decal, 0, sizeof(*decal));
10636 if (decalsystem->freedecal > i)
10637 decalsystem->freedecal = i;
10641 decal = decalsystem->decals;
10642 while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
10645 // collapse the array by shuffling the tail decals into the gaps
10648 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
10649 decalsystem->freedecal++;
10650 if (decalsystem->freedecal == numdecals)
10652 decal[decalsystem->freedecal] = decal[--numdecals];
10655 decalsystem->numdecals = numdecals;
10657 if (numdecals <= 0)
10659 // if there are no decals left, reset decalsystem
10660 R_DecalSystem_Reset(decalsystem);
10664 extern skinframe_t *decalskinframe;
10665 static void R_DrawModelDecals_Entity(entity_render_t *ent)
10668 decalsystem_t *decalsystem = &ent->decalsystem;
10677 const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
10680 numdecals = decalsystem->numdecals;
10684 if (r_showsurfaces.integer)
10687 if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10689 R_DecalSystem_Reset(decalsystem);
10693 // if the model is static it doesn't matter what value we give for
10694 // wantnormals and wanttangents, so this logic uses only rules applicable
10695 // to a model, knowing that they are meaningless otherwise
10696 if (ent == r_refdef.scene.worldentity)
10697 RSurf_ActiveWorldEntity();
10699 RSurf_ActiveModelEntity(ent, false, false, false);
10701 decalsystem->lastupdatetime = cl.time;
10702 decal = decalsystem->decals;
10704 faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
10706 // update vertex positions for animated models
10707 v3f = decalsystem->vertex3f;
10708 c4f = decalsystem->color4f;
10709 t2f = decalsystem->texcoord2f;
10710 for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
10712 if (!decal->color4f[0][3])
10715 if (surfacevisible && !surfacevisible[decal->surfaceindex])
10718 // update color values for fading decals
10719 if (decal->lived >= cl_decals_time.value)
10720 alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
10724 c4f[ 0] = decal->color4f[0][0] * alpha;
10725 c4f[ 1] = decal->color4f[0][1] * alpha;
10726 c4f[ 2] = decal->color4f[0][2] * alpha;
10728 c4f[ 4] = decal->color4f[1][0] * alpha;
10729 c4f[ 5] = decal->color4f[1][1] * alpha;
10730 c4f[ 6] = decal->color4f[1][2] * alpha;
10732 c4f[ 8] = decal->color4f[2][0] * alpha;
10733 c4f[ 9] = decal->color4f[2][1] * alpha;
10734 c4f[10] = decal->color4f[2][2] * alpha;
10737 t2f[0] = decal->texcoord2f[0][0];
10738 t2f[1] = decal->texcoord2f[0][1];
10739 t2f[2] = decal->texcoord2f[1][0];
10740 t2f[3] = decal->texcoord2f[1][1];
10741 t2f[4] = decal->texcoord2f[2][0];
10742 t2f[5] = decal->texcoord2f[2][1];
10744 // update vertex positions for animated models
10745 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
10747 e = rsurface.modelelement3i + 3*decal->triangleindex;
10748 VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
10749 VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
10750 VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
10754 VectorCopy(decal->vertex3f[0], v3f);
10755 VectorCopy(decal->vertex3f[1], v3f + 3);
10756 VectorCopy(decal->vertex3f[2], v3f + 6);
10759 if (r_refdef.fogenabled)
10761 alpha = RSurf_FogVertex(v3f);
10762 VectorScale(c4f, alpha, c4f);
10763 alpha = RSurf_FogVertex(v3f + 3);
10764 VectorScale(c4f + 4, alpha, c4f + 4);
10765 alpha = RSurf_FogVertex(v3f + 6);
10766 VectorScale(c4f + 8, alpha, c4f + 8);
10777 r_refdef.stats.drawndecals += numtris;
10779 // now render the decals all at once
10780 // (this assumes they all use one particle font texture!)
10781 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);
10782 // R_Mesh_ResetTextureState();
10783 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
10784 GL_DepthMask(false);
10785 GL_DepthRange(0, 1);
10786 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
10787 GL_DepthTest(true);
10788 GL_CullFace(GL_NONE);
10789 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
10790 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
10791 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
10795 static void R_DrawModelDecals(void)
10799 // fade faster when there are too many decals
10800 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10801 for (i = 0;i < r_refdef.scene.numentities;i++)
10802 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10804 R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
10805 for (i = 0;i < r_refdef.scene.numentities;i++)
10806 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10807 R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
10809 R_DecalSystem_ApplySplatEntitiesQueue();
10811 numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
10812 for (i = 0;i < r_refdef.scene.numentities;i++)
10813 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
10815 r_refdef.stats.totaldecals += numdecals;
10817 if (r_showsurfaces.integer)
10820 R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
10822 for (i = 0;i < r_refdef.scene.numentities;i++)
10824 if (!r_refdef.viewcache.entityvisible[i])
10826 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
10827 R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
10831 extern cvar_t mod_collision_bih;
10832 void R_DrawDebugModel(void)
10834 entity_render_t *ent = rsurface.entity;
10835 int i, j, k, l, flagsmask;
10836 const msurface_t *surface;
10837 dp_model_t *model = ent->model;
10840 switch(vid.renderpath)
10842 case RENDERPATH_GL11:
10843 case RENDERPATH_GL13:
10844 case RENDERPATH_GL20:
10846 case RENDERPATH_D3D9:
10847 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10849 case RENDERPATH_D3D10:
10850 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10852 case RENDERPATH_D3D11:
10853 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10855 case RENDERPATH_SOFT:
10856 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10858 case RENDERPATH_GLES2:
10859 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
10863 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
10865 // R_Mesh_ResetTextureState();
10866 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10867 GL_DepthRange(0, 1);
10868 GL_DepthTest(!r_showdisabledepthtest.integer);
10869 GL_DepthMask(false);
10870 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10872 if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
10876 qboolean cullbox = ent == r_refdef.scene.worldentity;
10877 const q3mbrush_t *brush;
10878 const bih_t *bih = &model->collision_bih;
10879 const bih_leaf_t *bihleaf;
10880 float vertex3f[3][3];
10881 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
10883 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
10885 if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
10887 switch (bihleaf->type)
10890 brush = model->brush.data_brushes + bihleaf->itemindex;
10891 if (brush->colbrushf && brush->colbrushf->numtriangles)
10893 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);
10894 R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
10895 R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
10898 case BIH_COLLISIONTRIANGLE:
10899 triangleindex = bihleaf->itemindex;
10900 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
10901 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
10902 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
10903 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);
10904 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10905 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10907 case BIH_RENDERTRIANGLE:
10908 triangleindex = bihleaf->itemindex;
10909 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
10910 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
10911 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
10912 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);
10913 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
10914 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
10920 GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10922 if (r_showtris.integer || (r_shownormals.value != 0))
10924 if (r_showdisabledepthtest.integer)
10926 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10927 GL_DepthMask(false);
10931 GL_BlendFunc(GL_ONE, GL_ZERO);
10932 GL_DepthMask(true);
10934 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
10936 if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
10938 rsurface.texture = R_GetCurrentTexture(surface->texture);
10939 if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
10941 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
10942 if (r_showtris.value > 0)
10944 if (!rsurface.texture->currentlayers->depthmask)
10945 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
10946 else if (ent == r_refdef.scene.worldentity)
10947 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
10949 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
10950 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10951 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10953 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10956 if (r_shownormals.value < 0)
10958 qglBegin(GL_LINES);
10959 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10961 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10962 GL_Color(0, 0, r_refdef.view.colorscale, 1);
10963 qglVertex3f(v[0], v[1], v[2]);
10964 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
10965 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10966 qglVertex3f(v[0], v[1], v[2]);
10971 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
10973 qglBegin(GL_LINES);
10974 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10976 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10977 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
10978 qglVertex3f(v[0], v[1], v[2]);
10979 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
10980 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10981 qglVertex3f(v[0], v[1], v[2]);
10985 qglBegin(GL_LINES);
10986 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
10988 VectorCopy(rsurface.batchvertex3f + l * 3, v);
10989 GL_Color(0, r_refdef.view.colorscale, 0, 1);
10990 qglVertex3f(v[0], v[1], v[2]);
10991 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
10992 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
10993 qglVertex3f(v[0], v[1], v[2]);
10997 qglBegin(GL_LINES);
10998 for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11000 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11001 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11002 qglVertex3f(v[0], v[1], v[2]);
11003 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11004 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11005 qglVertex3f(v[0], v[1], v[2]);
11012 rsurface.texture = NULL;
11016 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11017 int r_maxsurfacelist = 0;
11018 const msurface_t **r_surfacelist = NULL;
11019 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11021 int i, j, endj, flagsmask;
11022 dp_model_t *model = r_refdef.scene.worldmodel;
11023 msurface_t *surfaces;
11024 unsigned char *update;
11025 int numsurfacelist = 0;
11029 if (r_maxsurfacelist < model->num_surfaces)
11031 r_maxsurfacelist = model->num_surfaces;
11033 Mem_Free((msurface_t**)r_surfacelist);
11034 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11037 RSurf_ActiveWorldEntity();
11039 surfaces = model->data_surfaces;
11040 update = model->brushq1.lightmapupdateflags;
11042 // update light styles on this submodel
11043 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11045 model_brush_lightstyleinfo_t *style;
11046 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11048 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11050 int *list = style->surfacelist;
11051 style->value = r_refdef.scene.lightstylevalue[style->style];
11052 for (j = 0;j < style->numsurfaces;j++)
11053 update[list[j]] = true;
11058 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11062 R_DrawDebugModel();
11063 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11067 rsurface.lightmaptexture = NULL;
11068 rsurface.deluxemaptexture = NULL;
11069 rsurface.uselightmaptexture = false;
11070 rsurface.texture = NULL;
11071 rsurface.rtlight = NULL;
11072 numsurfacelist = 0;
11073 // add visible surfaces to draw list
11074 for (i = 0;i < model->nummodelsurfaces;i++)
11076 j = model->sortedmodelsurfaces[i];
11077 if (r_refdef.viewcache.world_surfacevisible[j])
11078 r_surfacelist[numsurfacelist++] = surfaces + j;
11080 // update lightmaps if needed
11081 if (model->brushq1.firstrender)
11083 model->brushq1.firstrender = false;
11084 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11086 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11090 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11091 if (r_refdef.viewcache.world_surfacevisible[j])
11093 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11095 // don't do anything if there were no surfaces
11096 if (!numsurfacelist)
11098 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11101 R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11103 // add to stats if desired
11104 if (r_speeds.integer && !skysurfaces && !depthonly)
11106 r_refdef.stats.world_surfaces += numsurfacelist;
11107 for (j = 0;j < numsurfacelist;j++)
11108 r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11111 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11114 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11116 int i, j, endj, flagsmask;
11117 dp_model_t *model = ent->model;
11118 msurface_t *surfaces;
11119 unsigned char *update;
11120 int numsurfacelist = 0;
11124 if (r_maxsurfacelist < model->num_surfaces)
11126 r_maxsurfacelist = model->num_surfaces;
11128 Mem_Free((msurface_t **)r_surfacelist);
11129 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11132 // if the model is static it doesn't matter what value we give for
11133 // wantnormals and wanttangents, so this logic uses only rules applicable
11134 // to a model, knowing that they are meaningless otherwise
11135 if (ent == r_refdef.scene.worldentity)
11136 RSurf_ActiveWorldEntity();
11137 else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11138 RSurf_ActiveModelEntity(ent, false, false, false);
11140 RSurf_ActiveModelEntity(ent, true, true, true);
11141 else if (depthonly)
11143 switch (vid.renderpath)
11145 case RENDERPATH_GL20:
11146 case RENDERPATH_D3D9:
11147 case RENDERPATH_D3D10:
11148 case RENDERPATH_D3D11:
11149 case RENDERPATH_SOFT:
11150 case RENDERPATH_GLES2:
11151 RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11153 case RENDERPATH_GL13:
11154 case RENDERPATH_GL11:
11155 RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11161 switch (vid.renderpath)
11163 case RENDERPATH_GL20:
11164 case RENDERPATH_D3D9:
11165 case RENDERPATH_D3D10:
11166 case RENDERPATH_D3D11:
11167 case RENDERPATH_SOFT:
11168 case RENDERPATH_GLES2:
11169 RSurf_ActiveModelEntity(ent, true, true, false);
11171 case RENDERPATH_GL13:
11172 case RENDERPATH_GL11:
11173 RSurf_ActiveModelEntity(ent, true, false, false);
11178 surfaces = model->data_surfaces;
11179 update = model->brushq1.lightmapupdateflags;
11181 // update light styles
11182 if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11184 model_brush_lightstyleinfo_t *style;
11185 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11187 if (style->value != r_refdef.scene.lightstylevalue[style->style])
11189 int *list = style->surfacelist;
11190 style->value = r_refdef.scene.lightstylevalue[style->style];
11191 for (j = 0;j < style->numsurfaces;j++)
11192 update[list[j]] = true;
11197 flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11201 R_DrawDebugModel();
11202 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11206 rsurface.lightmaptexture = NULL;
11207 rsurface.deluxemaptexture = NULL;
11208 rsurface.uselightmaptexture = false;
11209 rsurface.texture = NULL;
11210 rsurface.rtlight = NULL;
11211 numsurfacelist = 0;
11212 // add visible surfaces to draw list
11213 for (i = 0;i < model->nummodelsurfaces;i++)
11214 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11215 // don't do anything if there were no surfaces
11216 if (!numsurfacelist)
11218 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11221 // update lightmaps if needed
11225 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11230 R_BuildLightMap(ent, surfaces + j);
11235 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11237 R_BuildLightMap(ent, surfaces + j);
11238 R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11240 // add to stats if desired
11241 if (r_speeds.integer && !skysurfaces && !depthonly)
11243 r_refdef.stats.entities_surfaces += numsurfacelist;
11244 for (j = 0;j < numsurfacelist;j++)
11245 r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11248 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11251 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11253 static texture_t texture;
11254 static msurface_t surface;
11255 const msurface_t *surfacelist = &surface;
11257 // fake enough texture and surface state to render this geometry
11259 texture.update_lastrenderframe = -1; // regenerate this texture
11260 texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11261 texture.currentskinframe = skinframe;
11262 texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11263 texture.offsetmapping = OFFSETMAPPING_OFF;
11264 texture.offsetscale = 1;
11265 texture.specularscalemod = 1;
11266 texture.specularpowermod = 1;
11268 surface.texture = &texture;
11269 surface.num_triangles = numtriangles;
11270 surface.num_firsttriangle = firsttriangle;
11271 surface.num_vertices = numvertices;
11272 surface.num_firstvertex = firstvertex;
11275 rsurface.texture = R_GetCurrentTexture(surface.texture);
11276 rsurface.lightmaptexture = NULL;
11277 rsurface.deluxemaptexture = NULL;
11278 rsurface.uselightmaptexture = false;
11279 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11282 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)
11284 static msurface_t surface;
11285 const msurface_t *surfacelist = &surface;
11287 // fake enough texture and surface state to render this geometry
11288 surface.texture = texture;
11289 surface.num_triangles = numtriangles;
11290 surface.num_firsttriangle = firsttriangle;
11291 surface.num_vertices = numvertices;
11292 surface.num_firstvertex = firstvertex;
11295 rsurface.texture = R_GetCurrentTexture(surface.texture);
11296 rsurface.lightmaptexture = NULL;
11297 rsurface.deluxemaptexture = NULL;
11298 rsurface.uselightmaptexture = false;
11299 R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);